19 Commits

Author SHA1 Message Date
Dan Chao
edf704b469 Run spotless apply 2025-01-22 09:04:02 -08:00
Dan Chao
d9cfb68048 Prepare 0.27.2 release 2025-01-22 08:57:27 -08:00
Daniel Chao
1e75001382 Add release notes for 0.27.2 (#894) 2025-01-21 11:56:33 -08:00
Dan Chao
376eb2bdbf Run spotless apply 2025-01-17 10:32:24 -08:00
Daniel Chao
56a3b0a193 Update license year (#871)
* Update license header file spec to use placeholder year
* Update spotless to use ratchet formatting (only format files that have changed)
2025-01-17 10:32:24 -08:00
Josh B
6c8e45b19a Fix NPE when handling ExternalReader specs with null arguments (#882) 2025-01-17 10:32:24 -08:00
Josh B
0bc1b7156e Fix page size for Linux AArch64 native executables (#875)
Graal Native Image is assuming 4k page size here, which is a naughty assumption to make in the modern Linux-on-ARM landscape.
Two very common hardware configurations require 16k minumum page size: the Raspberry Pi 5 and Asahi Linux (running on Apple Silicon hardware).

This change forces 64k pages for Linux/AArch64 native executables to guarantee compatibility with these platforms.
DEVELOPMENT.adoc is also updated to cover the additional dependencies required for building native executables on Linux.
2025-01-17 10:32:24 -08:00
Stefan M.
f0b961de81 Make Test Report locale independent (#868)
Format numbers with `.` decimals
2025-01-17 10:32:24 -08:00
Daniel Chao
3ece353e0c Download JDK for windows build (#851)
Don't use the system Java on Windows builds, instead download them from Adoptium.

Also:

* Fail job if curl returns a 4xx status code
* Add java version to `GradleJob`
2025-01-17 09:58:03 -08:00
Josh B
639cc2430e Fix CreateEvaluatorRequest decoding (#853)
Handle case when request specifies external reader with null arguments
2024-12-19 10:00:46 -08:00
Philip K.F. Hölzenspies
48a710f439 Prepare 0.27.1 release (#839) 2024-12-06 14:23:25 +00:00
Philip K.F. Hölzenspies
15d85b0660 Add release notes for 0.27.1 2024-12-06 13:25:39 +00:00
odenix
aeace8bb3c Improve lazy type checking of listings and mappings (#789)
Motivation:
- simplify implementation of lazy type checking
- fix correctness issues of lazy type checking (#785)

Changes:
- implement listing/mapping type cast via amendment (`parent`) instead of delegation (`delegate`)
- handle type checking of *computed* elements/entries in the same way as type checking of computed properties
  - ElementOrEntryNode is the equivalent of TypeCheckedPropertyNode
- remove fields VmListingOrMapping.delegate/typeNodeFrame/cachedMembers/checkedMembers
- fix #785 by executing all type casts between a member's owner and receiver
- fix #823 by storing owner and receiver directly
  instead of storing the mutable frame containing them (typeNodeFrame)
- remove overrides of VmObject methods that are no longer required
  - good for Truffle partial evaluation and JVM inlining
- revert a85a173faa except for added tests
- move `VmUtils.setOwner` and `VmUtils.setReceiver` and make them private
  - these methods aren't generally safe to use

Result:
- simpler code with greater optimization potential
  - VmListingOrMapping can now have both a type node and new members
- fewer changes to surrounding code
- smaller memory footprint
- better performance in some cases
- fixes https://github.com/apple/pkl/issues/785
- fixes https://github.com/apple/pkl/issues/823

Potential future optimizations:
- avoid lazy type checking overhead for untyped listings/mappings
- improve efficiency of forcing a typed listing/mapping
  - currently, lazy type checking will traverse the parent chain once per member,
    reducing the performance benefit of shallow-forcing
	  a listing/mapping over evaluating each member individually
- avoid creating an intermediate untyped listing/mapping in the following cases:
  - `new Listing<X> {...}`
  - amendment of `property: Listing<X>`
2024-12-06 14:00:23 +01:00
Islon Scherer
7b850dd6d9 Fix possible stack overflow in Listing/Mapping type checking (#826) 2024-12-06 13:58:29 +01:00
Daniel Chao
c2096f633b Exclude non file-based modules from synthesized *GatherImports task (#821)
This fixes an issue where certain modules tasks fail due to the plugin
attempting to analyze their imports, but the arguments may not actually be
Pkl modules.

For example, the pkldoc task accepts entire packages in its "sourceMoules" property.

This changes the gather imports logic to only analyze file-based modules.
This is also a performance improvement; non file-based modules are unlikely to import
files due to insufficient trust levels.

Also: fix a bug when generating pkldoc on Windows
2024-12-06 13:58:06 +01:00
translatenix
d6ba021e12 Fix length of listings with computed index (#797)
Motivation:
The following expression evaluates to 2 instead of 1:
new Listing { "value" } { [0 + 0] = "override" }.length

Changes:
- fix length computation in EntriesLiteralNode
- improve `api/listing` tests
- make snippet test failures diffable in IntelliJ

Result:
- fixes https://github.com/apple/pkl/issues/780
- improved dev experience in IntelliJ
2024-12-06 13:57:19 +01:00
Josh B
077497d9b8 Fix a possible deadlock during external reader process close (#786) (#787)
* Fix a possible deadlock during external reader process close

* Apply spotless

---------

Co-authored-by: Philip K.F. Hölzenspies <holzensp@gmail.com>
2024-11-08 13:18:13 -08:00
Nick Muerdter
552b301451 Fix broken link to documentation site in release notes (#784) 2024-11-05 12:58:43 -08:00
Dan Chao
d3ac4b288c Prepare 0.27.0 release 2024-11-05 09:51:48 -08:00
646 changed files with 9022 additions and 19510 deletions

View File

@@ -105,13 +105,18 @@ local buildNativeJobs: Mapping<String, BuildNativeJob> = new {
}
local gradleCheckJobs: Mapping<String, GradleCheckJob> = new {
["gradle-check"] {
["gradle-check-jdk17"] {
javaVersion = "17.0"
isRelease = false
os = "linux"
}
["gradle-check-jdk21"] {
javaVersion = "21.0"
isRelease = false
os = "linux"
}
["gradle-check-windows"] {
javaVersion = "21.0"
["gradle-check-jdk17-windows"] {
javaVersion = "17.0"
isRelease = false
os = "windows"
}
@@ -148,8 +153,6 @@ jobs {
command = #"""
# exclude build_artifacts.txt from publish
rm -f pkl-cli/build/executable/*.build_artifacts.txt
find pkl-cli/build/executable/* -type d | xargs rm -rf
rm -f pkl-cli/build/executable/resources
gh release create "${CIRCLE_TAG}" \
--title "${CIRCLE_TAG}" \
--target "${CIRCLE_SHA1}" \

View File

@@ -9,21 +9,10 @@ jobs:
- run:
command: /usr/sbin/softwareupdate --install-rosetta --agree-to-license
name: Installing Rosetta 2
- run:
command: |-
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_x64_mac_hotspot_21.0.5_11.tar.gz -o /tmp/jdk.tar.gz
mkdir $HOME/jdk \
&& cd $HOME/jdk \
&& cat /tmp/jdk.tar.gz | tar --strip-components=1 -xzC .
name: Set up environment
shell: '#!/bin/bash -exo pipefail'
- run:
command: |-
export PATH=~/staticdeps/bin:$PATH
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:macExecutableAmd64 pkl-core:testMacExecutableAmd64 pkl-server:testMacExecutableAmd64
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:macExecutableAmd64 pkl-core:testMacExecutableAmd64 pkl-server:testMacExecutableAmd64
name: gradle buildNative
- persist_to_workspace:
root: '.'
@@ -33,7 +22,6 @@ jobs:
path: ~/test-results
environment:
LANG: en_US.UTF-8
JAVA_HOME: /Users/distiller/jdk/Contents/Home
resource_class: macos.m1.large.gen1
macos:
xcode: 15.3.0
@@ -52,7 +40,7 @@ jobs:
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_x64_linux_hotspot_21.0.5_11.tar.gz -o /tmp/jdk.tar.gz
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
mkdir /jdk \
&& cd /jdk \
@@ -100,7 +88,7 @@ jobs:
- run:
command: |-
export PATH=~/staticdeps/bin:$PATH
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:linuxExecutableAmd64 pkl-core:testLinuxExecutableAmd64 pkl-server:testLinuxExecutableAmd64
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:linuxExecutableAmd64 pkl-core:testLinuxExecutableAmd64 pkl-server:testLinuxExecutableAmd64
name: gradle buildNative
- persist_to_workspace:
root: '.'
@@ -117,21 +105,10 @@ jobs:
pkl-cli-macOS-aarch64-release:
steps:
- checkout
- run:
command: |-
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_aarch64_mac_hotspot_21.0.5_11.tar.gz -o /tmp/jdk.tar.gz
mkdir $HOME/jdk \
&& cd $HOME/jdk \
&& cat /tmp/jdk.tar.gz | tar --strip-components=1 -xzC .
name: Set up environment
shell: '#!/bin/bash -exo pipefail'
- run:
command: |-
export PATH=~/staticdeps/bin:$PATH
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:macExecutableAarch64 pkl-core:testMacExecutableAarch64 pkl-server:testMacExecutableAarch64
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:macExecutableAarch64 pkl-core:testMacExecutableAarch64 pkl-server:testMacExecutableAarch64
name: gradle buildNative
- persist_to_workspace:
root: '.'
@@ -141,7 +118,6 @@ jobs:
path: ~/test-results
environment:
LANG: en_US.UTF-8
JAVA_HOME: /Users/distiller/jdk/Contents/Home
resource_class: macos.m1.large.gen1
macos:
xcode: 15.3.0
@@ -160,7 +136,7 @@ jobs:
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_aarch64_linux_hotspot_21.0.5_11.tar.gz -o /tmp/jdk.tar.gz
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_aarch64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
mkdir /jdk \
&& cd /jdk \
@@ -192,7 +168,7 @@ jobs:
- run:
command: |-
export PATH=~/staticdeps/bin:$PATH
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:linuxExecutableAarch64 pkl-core:testLinuxExecutableAarch64 pkl-server:testLinuxExecutableAarch64
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:linuxExecutableAarch64 pkl-core:testLinuxExecutableAarch64 pkl-server:testLinuxExecutableAarch64
name: gradle buildNative
- persist_to_workspace:
root: '.'
@@ -221,7 +197,7 @@ jobs:
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_x64_linux_hotspot_21.0.5_11.tar.gz -o /tmp/jdk.tar.gz
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
mkdir /jdk \
&& cd /jdk \
@@ -269,7 +245,7 @@ jobs:
- run:
command: |-
export PATH=~/staticdeps/bin:$PATH
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:alpineExecutableAmd64 pkl-core:testAlpineExecutableAmd64 pkl-server:testAlpineExecutableAmd64
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:alpineExecutableAmd64 pkl-core:testAlpineExecutableAmd64 pkl-server:testAlpineExecutableAmd64
name: gradle buildNative
- persist_to_workspace:
root: '.'
@@ -290,7 +266,7 @@ jobs:
command: |-
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_x64_windows_hotspot_21.0.5_11.zip -o /tmp/jdk.zip
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9.1/OpenJDK17U-jdk_x64_windows_hotspot_17.0.9_9.zip -o /tmp/jdk.zip
unzip /tmp/jdk.zip -d /tmp/jdk \
&& cd /tmp/jdk/jdk-* \
@@ -301,7 +277,7 @@ jobs:
- run:
command: |-
export PATH=~/staticdeps/bin:$PATH
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:windowsExecutableAmd64 pkl-core:testWindowsExecutableAmd64 pkl-server:testWindowsExecutableAmd64
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:windowsExecutableAmd64 pkl-core:testWindowsExecutableAmd64 pkl-server:testWindowsExecutableAmd64
name: gradle buildNative
shell: bash.exe
- persist_to_workspace:
@@ -322,21 +298,10 @@ jobs:
- run:
command: /usr/sbin/softwareupdate --install-rosetta --agree-to-license
name: Installing Rosetta 2
- run:
command: |-
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_x64_mac_hotspot_21.0.5_11.tar.gz -o /tmp/jdk.tar.gz
mkdir $HOME/jdk \
&& cd $HOME/jdk \
&& cat /tmp/jdk.tar.gz | tar --strip-components=1 -xzC .
name: Set up environment
shell: '#!/bin/bash -exo pipefail'
- run:
command: |-
export PATH=~/staticdeps/bin:$PATH
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true pkl-cli:macExecutableAmd64 pkl-core:testMacExecutableAmd64 pkl-server:testMacExecutableAmd64
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:macExecutableAmd64 pkl-core:testMacExecutableAmd64 pkl-server:testMacExecutableAmd64
name: gradle buildNative
- persist_to_workspace:
root: '.'
@@ -346,7 +311,6 @@ jobs:
path: ~/test-results
environment:
LANG: en_US.UTF-8
JAVA_HOME: /Users/distiller/jdk/Contents/Home
resource_class: macos.m1.large.gen1
macos:
xcode: 15.3.0
@@ -365,7 +329,7 @@ jobs:
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_x64_linux_hotspot_21.0.5_11.tar.gz -o /tmp/jdk.tar.gz
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
mkdir /jdk \
&& cd /jdk \
@@ -413,7 +377,7 @@ jobs:
- run:
command: |-
export PATH=~/staticdeps/bin:$PATH
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true pkl-cli:linuxExecutableAmd64 pkl-core:testLinuxExecutableAmd64 pkl-server:testLinuxExecutableAmd64
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:linuxExecutableAmd64 pkl-core:testLinuxExecutableAmd64 pkl-server:testLinuxExecutableAmd64
name: gradle buildNative
- persist_to_workspace:
root: '.'
@@ -430,21 +394,10 @@ jobs:
pkl-cli-macOS-aarch64-snapshot:
steps:
- checkout
- run:
command: |-
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_aarch64_mac_hotspot_21.0.5_11.tar.gz -o /tmp/jdk.tar.gz
mkdir $HOME/jdk \
&& cd $HOME/jdk \
&& cat /tmp/jdk.tar.gz | tar --strip-components=1 -xzC .
name: Set up environment
shell: '#!/bin/bash -exo pipefail'
- run:
command: |-
export PATH=~/staticdeps/bin:$PATH
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true pkl-cli:macExecutableAarch64 pkl-core:testMacExecutableAarch64 pkl-server:testMacExecutableAarch64
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:macExecutableAarch64 pkl-core:testMacExecutableAarch64 pkl-server:testMacExecutableAarch64
name: gradle buildNative
- persist_to_workspace:
root: '.'
@@ -454,7 +407,6 @@ jobs:
path: ~/test-results
environment:
LANG: en_US.UTF-8
JAVA_HOME: /Users/distiller/jdk/Contents/Home
resource_class: macos.m1.large.gen1
macos:
xcode: 15.3.0
@@ -473,7 +425,7 @@ jobs:
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_aarch64_linux_hotspot_21.0.5_11.tar.gz -o /tmp/jdk.tar.gz
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_aarch64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
mkdir /jdk \
&& cd /jdk \
@@ -505,7 +457,7 @@ jobs:
- run:
command: |-
export PATH=~/staticdeps/bin:$PATH
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true pkl-cli:linuxExecutableAarch64 pkl-core:testLinuxExecutableAarch64 pkl-server:testLinuxExecutableAarch64
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:linuxExecutableAarch64 pkl-core:testLinuxExecutableAarch64 pkl-server:testLinuxExecutableAarch64
name: gradle buildNative
- persist_to_workspace:
root: '.'
@@ -534,7 +486,7 @@ jobs:
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_x64_linux_hotspot_21.0.5_11.tar.gz -o /tmp/jdk.tar.gz
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
mkdir /jdk \
&& cd /jdk \
@@ -582,7 +534,7 @@ jobs:
- run:
command: |-
export PATH=~/staticdeps/bin:$PATH
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true pkl-cli:alpineExecutableAmd64 pkl-core:testAlpineExecutableAmd64 pkl-server:testAlpineExecutableAmd64
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:alpineExecutableAmd64 pkl-core:testAlpineExecutableAmd64 pkl-server:testAlpineExecutableAmd64
name: gradle buildNative
- persist_to_workspace:
root: '.'
@@ -603,7 +555,7 @@ jobs:
command: |-
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_x64_windows_hotspot_21.0.5_11.zip -o /tmp/jdk.zip
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9.1/OpenJDK17U-jdk_x64_windows_hotspot_17.0.9_9.zip -o /tmp/jdk.zip
unzip /tmp/jdk.zip -d /tmp/jdk \
&& cd /tmp/jdk/jdk-* \
@@ -614,7 +566,7 @@ jobs:
- run:
command: |-
export PATH=~/staticdeps/bin:$PATH
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true pkl-cli:windowsExecutableAmd64 pkl-core:testWindowsExecutableAmd64 pkl-server:testWindowsExecutableAmd64
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:windowsExecutableAmd64 pkl-core:testWindowsExecutableAmd64 pkl-server:testWindowsExecutableAmd64
name: gradle buildNative
shell: bash.exe
- persist_to_workspace:
@@ -629,11 +581,23 @@ jobs:
resource_class: windows.large
machine:
image: windows-server-2022-gui:current
gradle-check:
gradle-check-jdk17:
steps:
- checkout
- run:
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true check
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results check
name: gradle check
- store_test_results:
path: ~/test-results
environment:
LANG: en_US.UTF-8
docker:
- image: cimg/openjdk:17.0
gradle-check-jdk21:
steps:
- checkout
- run:
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results check
name: gradle check
- store_test_results:
path: ~/test-results
@@ -641,14 +605,14 @@ jobs:
LANG: en_US.UTF-8
docker:
- image: cimg/openjdk:21.0
gradle-check-windows:
gradle-check-jdk17-windows:
steps:
- checkout
- run:
command: |-
# install jdk
curl -Lf \
https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_x64_windows_hotspot_21.0.5_11.zip -o /tmp/jdk.zip
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9.1/OpenJDK17U-jdk_x64_windows_hotspot_17.0.9_9.zip -o /tmp/jdk.zip
unzip /tmp/jdk.zip -d /tmp/jdk \
&& cd /tmp/jdk/jdk-* \
@@ -657,7 +621,7 @@ jobs:
name: Set up environment
shell: bash.exe
- run:
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true check
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results check
name: gradle check
- store_test_results:
path: ~/test-results
@@ -671,20 +635,20 @@ jobs:
steps:
- checkout
- run:
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true bench:jmh
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results bench:jmh
name: bench:jmh
- store_test_results:
path: ~/test-results
environment:
LANG: en_US.UTF-8
docker:
- image: cimg/openjdk:21.0
- image: cimg/openjdk:17.0
gradle-compatibility:
steps:
- checkout
- run:
command: |-
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true :pkl-gradle:build \
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results :pkl-gradle:build \
:pkl-gradle:compatibilityTestReleases
name: gradle compatibility
- store_test_results:
@@ -692,14 +656,14 @@ jobs:
environment:
LANG: en_US.UTF-8
docker:
- image: cimg/openjdk:21.0
- image: cimg/openjdk:17.0
deploy-snapshot:
steps:
- checkout
- attach_workspace:
at: '.'
- run:
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true publishToSonatype
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results publishToSonatype
- persist_to_workspace:
root: '.'
paths:
@@ -709,14 +673,14 @@ jobs:
environment:
LANG: en_US.UTF-8
docker:
- image: cimg/openjdk:21.0
- image: cimg/openjdk:17.0
deploy-release:
steps:
- checkout
- attach_workspace:
at: '.'
- run:
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true publishToSonatype closeAndReleaseSonatypeStagingRepository
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true publishToSonatype closeAndReleaseSonatypeStagingRepository
- persist_to_workspace:
root: '.'
paths:
@@ -726,7 +690,7 @@ jobs:
environment:
LANG: en_US.UTF-8
docker:
- image: cimg/openjdk:21.0
- image: cimg/openjdk:17.0
github-release:
steps:
- attach_workspace:
@@ -735,8 +699,6 @@ jobs:
command: |-
# exclude build_artifacts.txt from publish
rm -f pkl-cli/build/executable/*.build_artifacts.txt
find pkl-cli/build/executable/* -type d | xargs rm -rf
rm -f pkl-cli/build/executable/resources
gh release create "${CIRCLE_TAG}" \
--title "${CIRCLE_TAG}" \
--target "${CIRCLE_SHA1}" \
@@ -780,10 +742,13 @@ workflows:
type: approval
- pr-approval/authenticate:
context: pkl-pr-approval
- gradle-check:
- gradle-check-jdk17:
requires:
- hold
- gradle-check-windows:
- gradle-check-jdk21:
requires:
- hold
- gradle-check-jdk17-windows:
requires:
- hold
when:
@@ -792,8 +757,9 @@ workflows:
pattern: ^pull/\d+(/head)?$
main:
jobs:
- gradle-check
- gradle-check-windows
- gradle-check-jdk17
- gradle-check-jdk21
- gradle-check-jdk17-windows
- bench
- gradle-compatibility
- pkl-cli-macOS-amd64-snapshot
@@ -804,8 +770,9 @@ workflows:
- pkl-cli-windows-amd64-snapshot
- deploy-snapshot:
requires:
- gradle-check
- gradle-check-windows
- gradle-check-jdk17
- gradle-check-jdk21
- gradle-check-jdk17-windows
- bench
- gradle-compatibility
- pkl-cli-macOS-amd64-snapshot
@@ -826,13 +793,19 @@ workflows:
- << pipeline.git.branch >>
release:
jobs:
- gradle-check:
- gradle-check-jdk17:
filters:
branches:
ignore: /.*/
tags:
only: /^v?\d+\.\d+\.\d+$/
- gradle-check-windows:
- gradle-check-jdk21:
filters:
branches:
ignore: /.*/
tags:
only: /^v?\d+\.\d+\.\d+$/
- gradle-check-jdk17-windows:
filters:
branches:
ignore: /.*/
@@ -888,8 +861,9 @@ workflows:
only: /^v?\d+\.\d+\.\d+$/
- github-release:
requires:
- gradle-check
- gradle-check-windows
- gradle-check-jdk17
- gradle-check-jdk21
- gradle-check-jdk17-windows
- bench
- gradle-compatibility
- pkl-cli-macOS-amd64-release
@@ -925,8 +899,9 @@ workflows:
only: /^v?\d+\.\d+\.\d+$/
release-branch:
jobs:
- gradle-check
- gradle-check-windows
- gradle-check-jdk17
- gradle-check-jdk21
- gradle-check-jdk17-windows
- bench
- gradle-compatibility
- pkl-cli-macOS-amd64-release

View File

@@ -24,7 +24,7 @@ arch: "amd64"|"aarch64"
/// Whether to link to musl. Otherwise, links to glibc.
musl: Boolean = false
javaVersion = "21.0"
javaVersion = "17.0"
local setupLinuxEnvironment: Config.RunStep =
let (muslVersion = "1.2.2")
@@ -87,22 +87,6 @@ local setupLinuxEnvironment: Config.RunStep =
}.join("\n\n")
}
local setupMacEnvironment: Config.RunStep =
new {
name = "Set up environment"
shell = "#!/bin/bash -exo pipefail"
command =
#"""
# install jdk
curl -Lf \
https://github.com/adoptium/temurin\#(module.majorJdkVersion)-binaries/releases/download/\#(module.jdkGitHubReleaseName)/OpenJDK\#(module.majorJdkVersion)U-jdk_\#(if (arch == "amd64") "x64" else "aarch64")_mac_hotspot_\#(module.jdkVersionAlt).tar.gz -o /tmp/jdk.tar.gz
mkdir $HOME/jdk \
&& cd $HOME/jdk \
&& cat /tmp/jdk.tar.gz | tar --strip-components=1 -xzC .
"""#
}
steps {
when (os == "linux") {
new Config.RestoreCacheStep {
@@ -118,16 +102,13 @@ steps {
}
}
}
when (os == "macOS") {
when (arch == "amd64") {
new Config.RunStep {
name = "Installing Rosetta 2"
command = """
/usr/sbin/softwareupdate --install-rosetta --agree-to-license
"""
}
when (os == "macOS" && arch == "amd64") {
new Config.RunStep {
name = "Installing Rosetta 2"
command = """
/usr/sbin/softwareupdate --install-rosetta --agree-to-license
"""
}
setupMacEnvironment
}
new Config.RunStep {
name = "gradle buildNative"
@@ -159,9 +140,6 @@ job {
xcode = "15.3.0"
}
resource_class = "macos.m1.large.gen1"
environment {
["JAVA_HOME"] = "/Users/distiller/jdk/Contents/Home"
}
}
when (os == "linux") {
docker = new Listing<Config.DockerImage> {

View File

@@ -19,7 +19,7 @@ import "package://pkg.pkl-lang.org/pkl-pantry/com.circleci.v2@1.1.2#/Config.pkl"
local self = this
javaVersion = "21.0"
javaVersion = "17.0"
command: String

View File

@@ -47,7 +47,6 @@ fixed gradleArgs = new Listing {
"--info"
"--stacktrace"
"-DtestReportsDir=${HOME}/test-results"
"-DpklMultiJdkTesting=true"
when (isRelease) {
"-DreleaseBuild=true"
}

View File

@@ -23,7 +23,7 @@ command: String
os = "linux"
javaVersion = "21.0"
javaVersion = "17.0"
steps {
new Config.RunStep {

3
.gitignore vendored
View File

@@ -5,7 +5,6 @@
.gradle/
build/
generated/
testgenerated/
# IntelliJ
.idea/
@@ -23,5 +22,3 @@ testgenerated/
# :pkl-core:makeIntelliJAntlrPluginHappy
gen/
PklLexer.tokens
.kotlin/

View File

@@ -74,4 +74,4 @@
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>
</component>

View File

@@ -1 +1 @@
21
17.0

View File

@@ -2,12 +2,13 @@
:uri-gng: https://gng.dsun.org
:uri-jenv: https://www.jenv.be
:uri-intellij: https://www.jetbrains.com/idea/download/
:uri-jdk: https://adoptopenjdk.net/releases.html?variant=openjdk17
:uri-native-prerequisites-linux: https://www.graalvm.org/latest/getting-started/linux/#prerequisites-for-native-image-on-linux
:uri-native-prerequisites-windows: https://www.graalvm.org/latest/getting-started/windows/#prerequisites-for-native-image-on-windows
== Setup
. (mandatory) Install a JDK (JDK 21+ required).
. (mandatory) Install {uri-jdk}[OpenJDK 17] or higher
. (recommended) Install {uri-intellij}[IntelliJ IDEA] +
To import the project into IntelliJ, go to File->Open and select the project's root directory.
If the project is opened but not imported, look for a popup in the lower right corner
@@ -17,7 +18,7 @@ _gng_ enables to run Gradle commands with `gw` (instead of `./gradlew`) from any
. (recommended) Set up Git ignore-revs +
`git config blame.ignoreRevsFile .git-blame-ignore-revs`
. (recommended) Install {uri-jenv}[jenv] and plugins +
_jenv_ use specific JDK versions in certain subdirectories. _Pkl_ comes with a `.java-version` file specifying JDK 21. +
_jenv_ use specific JDK versions in certain subdirectories. _Pkl_ comes with a `.java-version` file specifying JDK 17. +
Enable _jenv_ plugins for better handling by `gradle`:
+
[source,shell]
@@ -83,8 +84,8 @@ based on version information from https://search.maven.org, https://plugins.grad
* Truffle code generation is performed by Truffle's annotation processor, which runs as part of task `:pkl-core:compileJava`
** Output dir is `generated/truffle/`
* ANTLR code generation is performed by task `:pkl-core:generateTestGrammarSource`
** Output dir is `testgenerated/antlr/`
* ANTLR code generation is performed by task `:pkl-core:generateGrammarSource`
** Output dir is `generated/antlr/`
== Remote JVM Debugging
@@ -96,6 +97,12 @@ Example: `./gradlew test -Djvmdebug=true`
== Resources
For automated build setup examples see our https://github.com/apple/pkl/blob/main/.circleci/[CircleCI] jobs like our https://github.com/apple/pkl/blob/main/.circleci/jobs/BuildNativeJob.pkl[BuildNativeJob.pkl], where we build Pkl automatically.
=== ANTLR
* https://github.com/antlr/antlr4/blob/master/doc/index.md[Documentation]
* https://groups.google.com/forum/#!forum/antlr-discussion[Forums]
* https://github.com/mobileink/lab.clj.antlr/tree/main/doc[Some third-party docs]
=== Truffle
* http://ssw.jku.at/Research/Projects/JVM/Truffle.html[Homepage]

View File

@@ -26,7 +26,18 @@ Copyright © 2017 Square, Inc.
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
4) GeantyRef (https://github.com/leangen/geantyref)
4) ANTLR 4 Runtime (Optimized) (http://tunnelvisionlabs.com)
POM License: The BSD License - http://www.antlr.org/license.html
Copyright (c) 2012 Terence Parr and Sam Harwell
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5) GeantyRef (https://github.com/leangen/geantyref)
Manifest license URL: https://www.apache.org/licenses/LICENSE-2.0
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
@@ -36,7 +47,7 @@ Copyright © 2017 Kaqqao
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
5) commonmark-java core
6) commonmark-java core
POM License: The 2-Clause BSD License - https://opensource.org/licenses/BSD-2-Clause
Embedded license:
@@ -67,7 +78,7 @@ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6) commonmark-java extension for tables
7) commonmark-java extension for tables
POM License: The 2-Clause BSD License - https://opensource.org/licenses/BSD-2-Clause
Embedded license:
@@ -98,7 +109,7 @@ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7) jansi (http://fusesource.com/)
8) jansi (http://fusesource.com/)
Manifest license URL: https://www.apache.org/licenses/LICENSE-2.0
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
@@ -108,13 +119,13 @@ Copyright © Fusesource 2023
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
8) Graal Sdk (https://github.com/oracle/graal)
9) Graal Sdk (https://github.com/oracle/graal)
POM License: Universal Permissive License, Version 1.0 - http://opensource.org/licenses/UPL
9) Truffle API (http://openjdk.java.net/projects/graal)
10) Truffle API (http://openjdk.java.net/projects/graal)
POM License: Universal Permissive License, Version 1.0 - http://opensource.org/licenses/UPL
10) IntelliJ IDEA Annotations (http://www.jetbrains.org)
11) IntelliJ IDEA Annotations (http://www.jetbrains.org)
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
The Apache License
@@ -122,7 +133,7 @@ Copyright © Jetbrains 2023
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
11) kotlin-reflect (https://kotlinlang.org/)
12) kotlin-reflect (https://kotlinlang.org/)
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
The Apache License
@@ -130,7 +141,7 @@ Copyright © Wuseal 2018
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
12) kotlin-stdlib (https://kotlinlang.org/)
13) kotlin-stdlib (https://kotlinlang.org/)
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
The Apache License
@@ -138,7 +149,7 @@ Copyright © 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contribu
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
13) kotlin-stdlib-common (https://kotlinlang.org/)
14) kotlin-stdlib-common (https://kotlinlang.org/)
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
The Apache License
@@ -146,7 +157,7 @@ Copyright © 2023 Kotlin Team
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
14) kotlin-stdlib-jdk7 (https://kotlinlang.org/)
15) kotlin-stdlib-jdk7 (https://kotlinlang.org/)
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
The Apache License
@@ -154,7 +165,7 @@ Copyright © 2023 Kotlin Team
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
15) kotlin-stdlib-jdk8 (https://kotlinlang.org/)
16) kotlin-stdlib-jdk8 (https://kotlinlang.org/)
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
The Apache License
@@ -162,7 +173,7 @@ Copyright © 2023 Kotlin Team
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
16) kotlinx.html (https://github.com/Kotlin/kotlinx.html)
17) kotlinx.html (https://github.com/Kotlin/kotlinx.html)
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
The Apache License
@@ -170,7 +181,7 @@ Copyright © 2017 Yole
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
17) kotlinx-serialization-core (https://github.com/Kotlin/kotlinx.serialization)
18) kotlinx-serialization-core (https://github.com/Kotlin/kotlinx.serialization)
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
The Apache License
@@ -178,7 +189,7 @@ The Apache License
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18) kotlinx-serialization-json (https://github.com/Kotlin/kotlinx.serialization)
19) kotlinx-serialization-json (https://github.com/Kotlin/kotlinx.serialization)
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
The Apache License
@@ -186,7 +197,7 @@ The Apache License
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
19) JLine Reader
20) JLine Reader
Manifest license URL: https://opensource.org/licenses/BSD-3-Clause
POM License: The 3-Clause BSD License - https://opensource.org/licenses/BSD-3-Clause
@@ -205,7 +216,7 @@ software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20) JLine Terminal
21) JLine Terminal
Manifest license URL: https://opensource.org/licenses/BSD-3-Clause
POM License: The 3-Clause BSD License - https://opensource.org/licenses/BSD-3-Clause
@@ -224,7 +235,7 @@ software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21) JLine JANSI Terminal
22) JLine JANSI Terminal
Manifest license URL: https://opensource.org/licenses/BSD-3-Clause
POM License: The 3-Clause BSD License - https://opensource.org/licenses/BSD-3-Clause
@@ -243,7 +254,7 @@ software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22) msgpack-core (https://msgpack.org/)
23) msgpack-core (https://msgpack.org/)
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
The Apache License
@@ -251,7 +262,7 @@ Copyright © 2016 Sadayuki Furuhashi, Muga Nishizawa, Taro L. Saito, Mitsunori K
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
23) Paguro (https://github.com/GlenKPeterson/Paguro)
24) Paguro (https://github.com/GlenKPeterson/Paguro)
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
The Apache License
@@ -353,7 +364,7 @@ Everyone is permitted to copy and distribute copies of this Agreement, but in or
This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
24) SnakeYAML Engine (http://www.snakeyaml.org)
25) SnakeYAML Engine (http://www.snakeyaml.org)
Manifest license URL: https://www.apache.org/licenses/LICENSE-2.0
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,15 +16,18 @@
plugins {
pklAllProjects
pklJavaLibrary
pklGraalVm
id("me.champeau.jmh")
}
val truffle: Configuration by configurations.creating
val graal: Configuration by configurations.creating
@Suppress("UnstableApiUsage")
dependencies {
jmh(projects.pklCore)
jmh(projects.pklCommonsTest)
// necessary because antlr4-runtime is declared as implementation dependency in pkl-core.gradle
jmh(libs.antlrRuntime)
truffle(libs.truffleApi)
graal(libs.graalCompiler)
}

View File

@@ -1,62 +1,44 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
net.bytebuddy:byte-buddy:1.15.11=jmh,jmhRuntimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.tunnelvisionlabs:antlr4-runtime:4.9.0=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
net.bytebuddy:byte-buddy:1.14.18=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
net.sf.jopt-simple:jopt-simple:5.0.4=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
org.apache.commons:commons-math3:3.6.1=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
org.apiguardian:apiguardian-api:1.1.2=jmhCompileClasspath,jmhImplementationDependenciesMetadata,testCompileClasspath,testImplementationDependenciesMetadata,testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.27.3=jmh,jmhRuntimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.compiler:compiler:24.1.2=graal
org.graalvm.polyglot:polyglot:24.1.2=jmh,jmhRuntimeClasspath,truffle
org.graalvm.sdk:collections:24.1.2=graal,jmh,jmhRuntimeClasspath,truffle
org.graalvm.sdk:graal-sdk:24.1.2=jmh,jmhRuntimeClasspath
org.graalvm.sdk:nativeimage:24.1.2=jmh,jmhRuntimeClasspath,truffle
org.graalvm.sdk:word:24.1.2=graal,jmh,jmhRuntimeClasspath,truffle
org.graalvm.truffle:truffle-api:24.1.2=jmh,jmhRuntimeClasspath,truffle
org.graalvm.truffle:truffle-compiler:24.1.2=graal
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-build-tools-impl:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-compiler-runner:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-daemon-client:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:2.0.21=kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-native-prebuilt:2.0.21=kotlinNativeBundleConfiguration
org.jetbrains.kotlin:kotlin-reflect:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-script-runtime:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-scripting-common:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17
org.jetbrains.kotlin:kotlin-scripting-jvm:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17
org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.0.21=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.0.21=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:2.0.21=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains:annotations:13.0=jmh,jmhCompileClasspath,jmhRuntimeClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17,kotlinKlibCommonizerClasspath,testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.11.4=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-api:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.11.4=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-engine:5.8.2=testJdk17RuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.11.4=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.jupiter:junit-jupiter:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.platform:junit-platform-commons:1.11.4=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.platform:junit-platform-commons:1.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.platform:junit-platform-engine:1.11.4=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.platform:junit-platform-engine:1.8.2=testJdk17RuntimeClasspath
org.junit.platform:junit-platform-launcher:1.8.2=testJdk17RuntimeClasspath
org.junit:junit-bom:5.11.4=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit:junit-bom:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.compiler:compiler:23.0.6=graal
org.graalvm.sdk:graal-sdk:23.0.6=graal,jmh,jmhRuntimeClasspath,truffle
org.graalvm.truffle:truffle-api:23.0.6=graal,jmh,jmhRuntimeClasspath,truffle
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.7.10=kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-reflect:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-script-runtime:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-scripting-common:1.7.10=kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.7.10=kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.7.10=kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-jvm:1.7.10=kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains:annotations:13.0=kotlinCompilerClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-engine:5.11.3=testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-params:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.platform:junit-platform-engine:1.11.3=testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit:junit-bom:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.msgpack:msgpack-core:0.9.8=jmh,jmhRuntimeClasspath
org.openjdk.jmh:jmh-core:1.37=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
org.openjdk.jmh:jmh-generator-asm:1.37=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
org.openjdk.jmh:jmh-generator-bytecode:1.37=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
org.openjdk.jmh:jmh-generator-reflection:1.37=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
org.opentest4j:opentest4j:1.2.0=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.opentest4j:opentest4j:1.3.0=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.organicdesign:Paguro:3.10.3=jmh,jmhRuntimeClasspath
org.ow2.asm:asm:9.0=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
org.snakeyaml:snakeyaml-engine:2.9=jmh,jmhRuntimeClasspath
empty=annotationProcessor,apiDependenciesMetadata,compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,intransitiveDependenciesMetadata,jmhAnnotationProcessor,jmhApiDependenciesMetadata,jmhCompileOnlyDependenciesMetadata,jmhIntransitiveDependenciesMetadata,jmhKotlinScriptDef,jmhKotlinScriptDefExtensions,jmhRuntimeOnlyDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtimeClasspath,runtimeOnlyDependenciesMetadata,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testJdk17AnnotationProcessor,testJdk17ApiDependenciesMetadata,testJdk17CompileOnlyDependenciesMetadata,testJdk17IntransitiveDependenciesMetadata,testJdk17KotlinScriptDefExtensions,testKotlinScriptDef,testKotlinScriptDefExtensions
org.snakeyaml:snakeyaml-engine:2.5=jmh,jmhRuntimeClasspath
empty=annotationProcessor,apiDependenciesMetadata,compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,intransitiveDependenciesMetadata,jmhAnnotationProcessor,jmhApiDependenciesMetadata,jmhCompileOnlyDependenciesMetadata,jmhIntransitiveDependenciesMetadata,jmhKotlinScriptDef,jmhKotlinScriptDefExtensions,jmhRuntimeOnlyDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtimeClasspath,runtimeOnlyDependenciesMetadata,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,15 +15,8 @@
*/
package org.pkl.core.parser;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.*;
import org.pkl.commons.test.FileTestUtils;
import org.pkl.commons.test.FileTestUtilsKt;
import org.pkl.core.Release;
import org.pkl.core.util.IoUtils;
@SuppressWarnings("unused")
@Warmup(iterations = 5, time = 2)
@@ -31,33 +24,37 @@ import org.pkl.core.util.IoUtils;
@OutputTimeUnit(TimeUnit.SECONDS)
@Fork(1)
public class ParserBenchmark {
// One-time execution of this code took ~10s until moving rule alternative
// for parenthesized expression after alternative for anonymous function.
@Benchmark
public void parseStdlib() {
for (var stdlibModule : Release.current().standardLibrary().modules()) {
try {
var moduleSource =
IoUtils.readClassPathResourceAsString(
getClass(), "/org/pkl/core/stdlib/%s.pkl".formatted(stdlibModule.substring(4)));
new Parser().parseModule(moduleSource);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
@Benchmark
public void parseSnippetTests() {
var snippetTestDir =
FileTestUtils.getRootProjectDir()
.resolve("pkl-core/src/test/files/LanguageSnippetTests/input");
for (var snippet : FileTestUtilsKt.listFilesRecursively(snippetTestDir)) {
try {
var moduleSource = Files.readString(snippet);
new Parser().parseModule(moduleSource);
} catch (IOException e) {
throw new UncheckedIOException(e);
} catch (ParserError ignore) {
}
}
public void run() {
new Parser()
.parseModule(
"""
a1 {
a2 {
a3 {
a4 {
a5 {
a6 {
a7 {
a8 {
a9 {
a10 {
a11 {
a12 {
a13 = map(map(map((x) -> 1)))
}
}
}
}
}
}
}
}
}
}
}
}""");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,15 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
`kotlin-dsl`
`jvm-toolchains`
}
// Keep this in sync with the constants in `BuildInfo.kt` (those are not addressable here).
val toolchainVersion = 21
plugins { `kotlin-dsl` }
dependencies {
implementation(libs.downloadTaskPlugin)
@@ -35,16 +27,8 @@ dependencies {
}
java {
sourceCompatibility = JavaVersion.toVersion(toolchainVersion)
targetCompatibility = JavaVersion.toVersion(toolchainVersion)
toolchain {
languageVersion = JavaLanguageVersion.of(toolchainVersion)
vendor = JvmVendorSpec.ADOPTIUM
}
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(toolchainVersion)
compilerOptions { jvmTarget = JvmTarget.fromTarget(toolchainVersion.toString()) }
}
kotlin { target { compilations.configureEach { kotlinOptions { jvmTarget = "17" } } } }

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,8 +24,6 @@ pluginManagement {
}
}
plugins { id("org.gradle.toolchains.foojay-resolver-convention") }
// makes ~/.gradle/init.gradle unnecessary and ~/.gradle/gradle.properties optional
dependencyResolutionManagement {
// use same version catalog as main build

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,56 +19,11 @@ import java.io.File
import org.gradle.api.Project
import org.gradle.api.artifacts.VersionCatalog
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.api.attributes.Category
import org.gradle.api.plugins.JvmTestSuitePlugin
import org.gradle.api.plugins.jvm.JvmTestSuite
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.testing.Test
import org.gradle.internal.extensions.stdlib.capitalized
import org.gradle.jvm.toolchain.*
import org.gradle.kotlin.dsl.*
import org.gradle.kotlin.dsl.support.serviceOf
import org.gradle.process.CommandLineArgumentProvider
import org.gradle.testing.base.TestingExtension
/**
* JVM bytecode target; this is pinned at a reasonable version, because downstream JVM projects
* which consume Pkl will need a minimum Bytecode level at or above this one.
*
* Kotlin and Java need matching bytecode targets, so this is expressed as a build setting and
* constant default. To override, pass `-DpklJdkToolchain=X` to the Gradle command line, where X is
* a major Java version.
*/
const val PKL_JVM_TARGET_DEFAULT_MAXIMUM = 17
/**
* The Pkl build requires JDK 21+ to build, because JDK 17 is no longer within the default set of
* supported JDKs for GraalVM. This is a build-time requirement, not a runtime requirement.
*/
const val PKL_JDK_VERSION_MIN = 21
/**
* The JDK minimum is set to match the bytecode minimum, to guarantee that fat JARs work against the
* earliest supported bytecode target.
*/
const val PKL_TEST_JDK_MINIMUM = PKL_JVM_TARGET_DEFAULT_MAXIMUM
/**
* Maximum JDK version which Pkl is tested with; this should be bumped when new JDK stable releases
* are issued. At the time of this writing, JDK 23 is the latest available release.
*/
const val PKL_TEST_JDK_MAXIMUM = 23
/**
* Test the full suite of JDKs between [PKL_TEST_JDK_MINIMUM] and [PKL_TEST_JDK_MAXIMUM]; if this is
* set to `false` (or overridden on the command line), only LTS releases are tested by default.
*/
const val PKL_TEST_ALL_JDKS = false
import org.gradle.kotlin.dsl.getByType
// `buildInfo` in main build scripts
// `project.extensions.getByType<BuildInfo>()` in precompiled script plugins
open class BuildInfo(private val project: Project) {
open class BuildInfo(project: Project) {
inner class GraalVm(val arch: String) {
val homeDir: String by lazy {
System.getenv("GRAALVM_HOME") ?: "${System.getProperty("user.home")}/.graalvm"
@@ -95,11 +50,6 @@ open class BuildInfo(private val project: Project) {
"https://download.oracle.com/graalvm/$jdkMajor/archive/$baseName.$extension"
}
val downloadFile: File by lazy {
val extension = if (os.isWindows) "zip" else "tar.gz"
File(homeDir, "${baseName}.$extension")
}
val installDir: File by lazy { File(homeDir, baseName) }
val baseDir: String by lazy {
@@ -125,220 +75,6 @@ open class BuildInfo(private val project: Project) {
val isReleaseBuild: Boolean by lazy { java.lang.Boolean.getBoolean("releaseBuild") }
val isNativeArch: Boolean by lazy { java.lang.Boolean.getBoolean("nativeArch") }
val jvmTarget: Int by lazy {
System.getProperty("pklJvmTarget")?.toInt() ?: PKL_JVM_TARGET_DEFAULT_MAXIMUM
}
// JPMS exports for Truffle; needed on some versions of Java, and transitively within some JARs.
private val jpmsExports =
arrayOf(
"org.graalvm.truffle/com.oracle.truffle.api.exception=ALL-UNNAMED",
"org.graalvm.truffle/com.oracle.truffle.api=ALL-UNNAMED",
"org.graalvm.truffle/com.oracle.truffle.api.nodes=ALL-UNNAMED",
"org.graalvm.truffle/com.oracle.truffle.api.source=ALL-UNNAMED",
)
// Extra JPMS modules forced onto the module path via `--add-modules` in some cases.
private val jpmsAddModules = arrayOf("jdk.unsupported")
// Formats `jpmsExports` for use in JAR manifest attributes.
val jpmsExportsForJarManifest: String by lazy {
jpmsExports.joinToString(" ") { it.substringBefore("=") }
}
// Formats `jpmsExports` for use on the command line with `--add-exports`.
val jpmsExportsForAddExportsFlags: Collection<String> by lazy {
jpmsExports.map { "--add-exports=$it" }
}
// Formats `jpmsAddModules` for use on the command line with `--add-modules`.
val jpmsAddModulesFlags: Collection<String> by lazy { jpmsAddModules.map { "--add-modules=$it" } }
// JVM properties to set during testing.
val testProperties =
mapOf<String, Any>(
// @TODO: this should be removed once pkl supports JPMS as a true Java Module.
"polyglotimpl.DisableClassPathIsolation" to true
)
val jdkVendor: JvmVendorSpec = JvmVendorSpec.ADOPTIUM
val jdkToolchainVersion: JavaLanguageVersion by lazy {
JavaLanguageVersion.of(System.getProperty("pklJdkToolchain")?.toInt() ?: PKL_JDK_VERSION_MIN)
}
val jdkTestFloor: JavaLanguageVersion by lazy { JavaLanguageVersion.of(PKL_TEST_JDK_MINIMUM) }
val jdkTestCeiling: JavaLanguageVersion by lazy { JavaLanguageVersion.of(PKL_TEST_JDK_MAXIMUM) }
val testAllJdks: Boolean by lazy {
// By default, Pkl is tested against LTS JDK releases within the bounds of `PKL_TEST_JDK_TARGET`
// and `PKL_TEST_JDK_MAXIMUM`. To test against the full suite of JDK versions, past and present,
// set `-DpklTestAllJdks=true` on the Gradle command line. This results in non-LTS releases, old
// releases, and "experimental releases" (newer than the toolchain version) being included in
// the default `check` suite.
System.getProperty("pklTestAllJdks")?.toBoolean() ?: PKL_TEST_ALL_JDKS
}
val testExperimentalJdks: Boolean by lazy {
System.getProperty("pklTestFutureJdks")?.toBoolean() ?: false
}
val testJdkVendors: Sequence<JvmVendorSpec> by lazy {
// By default, only OpenJDK is tested during multi-JDK testing. Flip `-DpklTestAllVendors=true`
// to additionally test against a suite of JDK vendors, including Azul, Oracle, and GraalVM.
when (System.getProperty("pklTestAllVendors")?.toBoolean()) {
true -> sequenceOf(JvmVendorSpec.ADOPTIUM, JvmVendorSpec.GRAAL_VM, JvmVendorSpec.ORACLE)
else -> sequenceOf(JvmVendorSpec.ADOPTIUM)
}
}
// Assembles a collection of JDK versions which tests can be run against, considering ancillary
// parameters like `testAllJdks` and `testExperimentalJdks`.
val jdkTestRange: Collection<JavaLanguageVersion> by lazy {
JavaVersionRange.inclusive(jdkTestFloor, jdkTestCeiling).filter { version ->
// unless we are instructed to test all JDKs, tests only include LTS releases and
// versions above the toolchain version.
testAllJdks || (JavaVersionRange.isLTS(version) || version >= jdkToolchainVersion)
}
}
private fun JavaToolchainSpec.pklJdkToolchain() {
languageVersion.set(jdkToolchainVersion)
vendor.set(jdkVendor)
}
private fun labelForVendor(vendor: JvmVendorSpec): String =
when (vendor) {
JvmVendorSpec.AZUL -> "Zulu"
JvmVendorSpec.GRAAL_VM -> "GraalVm"
JvmVendorSpec.ORACLE -> "Oracle"
JvmVendorSpec.ADOPTIUM -> "Adoptium"
else -> error("Unrecognized JDK vendor: $vendor")
}
private fun testNamer(baseName: () -> String): (JavaLanguageVersion, JvmVendorSpec?) -> String =
{ jdkTarget, vendor ->
val targetToken =
when (vendor) {
null -> "Jdk${jdkTarget.asInt()}"
else -> "Jdk${jdkTarget.asInt()}${labelForVendor(vendor).capitalized()}"
}
if (jdkTarget > jdkToolchainVersion) {
// test targets above the toolchain target are considered "experimental".
"${baseName()}${targetToken}Experimental"
} else {
"${baseName()}${targetToken}"
}
}
@Suppress("UnstableApiUsage")
fun multiJdkTestingWith(
templateTask: TaskProvider<out Test>,
configurator: MultiJdkTestConfigurator = {},
): Iterable<Provider<out Any>> =
with(project) {
// force the `jvm-test-suite` plugin to apply first
project.pluginManager.apply(JvmTestSuitePlugin::class.java)
val isMultiVendor = testJdkVendors.count() > 1
val baseNameProvider = { templateTask.get().name }
val namer = testNamer(baseNameProvider)
val applyConfig: MultiJdkTestConfigurator = { (version, jdk) ->
// 1) copy configurations from the template task
dependsOn(templateTask)
templateTask.get().let { template ->
classpath = template.classpath
testClassesDirs = template.testClassesDirs
jvmArgs.addAll(template.jvmArgs)
jvmArgumentProviders.addAll(template.jvmArgumentProviders)
forkEvery = template.forkEvery
maxParallelForks = template.maxParallelForks
minHeapSize = template.minHeapSize
maxHeapSize = template.maxHeapSize
exclude(template.excludes)
template.systemProperties.forEach { prop -> systemProperty(prop.key, prop.value) }
}
// 2) assign launcher
javaLauncher = jdk
// 3) dispatch the user's configurator
configurator(version to jdk)
}
serviceOf<JavaToolchainService>().let { toolchains ->
jdkTestRange
.flatMap { targetVersion ->
// multiply out by jdk vendor
testJdkVendors.map { vendor -> (targetVersion to vendor) }
}
.filter { (jdkTarget, vendor) ->
// only include experimental tasks in the return suite if the flag is set. if the task
// is withheld from the returned list, it will not be executed by default with `gradle
// check`.
testExperimentalJdks ||
(!namer(jdkTarget, vendor.takeIf { isMultiVendor }).contains("Experimental"))
}
.map { (jdkTarget, vendor) ->
if (jdkToolchainVersion == jdkTarget)
tasks.register(namer(jdkTarget, vendor)) {
// alias to `test`
dependsOn(templateTask)
group = Category.VERIFICATION
description =
"Alias for regular '${baseNameProvider()}' task, on JDK ${jdkTarget.asInt()}"
}
else
the<TestingExtension>().suites.register(
namer(jdkTarget, vendor.takeIf { isMultiVendor }),
JvmTestSuite::class,
) {
targets.all {
testTask.configure {
group = Category.VERIFICATION
description = "Run tests against JDK ${jdkTarget.asInt()}"
applyConfig(jdkTarget to toolchains.launcherFor { languageVersion = jdkTarget })
// fix: on jdk17, we must force the polyglot module on to the modulepath
if (jdkTarget.asInt() == 17)
jvmArgumentProviders.add(
CommandLineArgumentProvider {
buildList { listOf("--add-modules=org.graalvm.polyglot") }
}
)
}
}
}
}
.toList()
}
}
val javaCompiler: Provider<JavaCompiler> by lazy {
project.serviceOf<JavaToolchainService>().let { toolchainService ->
toolchainService.compilerFor { pklJdkToolchain() }
}
}
val javaTestLauncher: Provider<JavaLauncher> by lazy {
project.serviceOf<JavaToolchainService>().let { toolchainService ->
toolchainService.launcherFor { pklJdkToolchain() }
}
}
val multiJdkTesting: Boolean by lazy {
// By default, Pkl is tested against a full range of JDK versions, past and present, within the
// supported bounds of `PKL_TEST_JDK_TARGET` and `PKL_TEST_JDK_MAXIMUM`. To opt-out of this
// behavior, set `-DpklMultiJdkTesting=false` on the Gradle command line.
//
// In CI, this defaults to `true` to catch potential cross-JDK compat regressions or other bugs.
// In local dev, this defaults to `false` to speed up the build and reduce contributor load.
System.getProperty("pklMultiJdkTesting")?.toBoolean() ?: isCiBuild
}
val hasMuslToolchain: Boolean by lazy {
// see "install musl" in .circleci/jobs/BuildNativeJob.pkl
File(System.getProperty("user.home"), "staticdeps/bin/x86_64-linux-musl-gcc").exists()
@@ -350,8 +86,6 @@ open class BuildInfo(private val project: Project) {
// could be `commitId: Provider<String> = project.provider { ... }`
val commitId: String by lazy {
// allow -DcommitId=abc123 for build environments that don't have git.
System.getProperty("commitId").let { if (it != null) return@lazy it }
// only run command once per build invocation
if (project === project.rootProject) {
val process =
@@ -397,7 +131,3 @@ open class BuildInfo(private val project: Project) {
}
}
}
// Shape of a function which is applied to configure multi-JDK testing.
private typealias MultiJdkTestConfigurator =
Test.(Pair<JavaLanguageVersion, Provider<JavaLauncher>>) -> Unit

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,11 +22,12 @@ import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
/**
* Builds a self-contained Pkl CLI Jar that is directly executable on Windows, macOS, and Linux.
* Builds a self-contained Pkl CLI Jar that is directly executable on *nix and executable with `java
* -jar` on Windows.
*
* For direct execution, the `java` command must be on the PATH.
*
* Technique borrowed from [Mill](https://mill-build.org/blog/5-executable-jars.html).
* https://skife.org/java/unix/2011/06/20/really_executable_jars.html
*/
abstract class ExecutableJar : DefaultTask() {
@get:InputFile abstract val inJar: RegularFileProperty
@@ -40,27 +41,12 @@ abstract class ExecutableJar : DefaultTask() {
val inFile = inJar.get().asFile
val outFile = outJar.get().asFile
val escapedJvmArgs = jvmArgs.get().joinToString(separator = " ") { "\"$it\"" }
val unixStartScript =
val startScript =
"""
@ 2>/dev/null # 2>nul & echo off & goto BOF
:
exec java $escapedJvmArgs -jar "$0" "$@"
exit
"""
.trimIndent()
val windowsStartScript =
"""
:BOF
setlocal
@echo off
java $escapedJvmArgs -jar "%~dpnx0" %*
endlocal
exit /B %errorlevel%
"""
.trimIndent()
// need crlf endings for Windows portion of script
.replace("\n", "\r\n")
val startScript = unixStartScript + "\r\n" + windowsStartScript + "\r\n".repeat(3)
#!/bin/sh
exec java $escapedJvmArgs -jar $0 "$@"
"""
.trimIndent() + "\n\n\n"
outFile.outputStream().use { outStream ->
startScript.byteInputStream().use { it.copyTo(outStream) }
inFile.inputStream().use { it.copyTo(outStream) }

View File

@@ -1,91 +0,0 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
import java.util.*
import javax.inject.Inject
import kotlin.io.path.createDirectories
import org.gradle.api.DefaultTask
import org.gradle.api.internal.file.FileOperations
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
import org.gradle.process.ExecOperations
abstract class InstallGraalVm
@Inject
constructor(
private val fileOperations: FileOperations,
private val execOperations: ExecOperations,
) : DefaultTask() {
@get:Input abstract val graalVm: Property<BuildInfo.GraalVm>
init {
@Suppress("LeakingThis") onlyIf("GraalVM not installed") { !graalVm.get().installDir.exists() }
}
@TaskAction
@Suppress("unused")
fun run() {
// minimize chance of corruption by extract-to-random-dir-and-flip-symlink
val distroDir = Paths.get(graalVm.get().homeDir, UUID.randomUUID().toString())
try {
distroDir.createDirectories()
println("Extracting ${graalVm.get().downloadFile} into $distroDir")
// faster and more reliable than Gradle's `copy { from tarTree() }`
execOperations.exec {
workingDir = distroDir.toFile()
executable = "tar"
args("--strip-components=1", "-xzf", graalVm.get().downloadFile)
}
val os = org.gradle.internal.os.OperatingSystem.current()
val distroBinDir =
if (os.isMacOsX) distroDir.resolve("Contents/Home/bin") else distroDir.resolve("bin")
println("Installing native-image into $distroDir")
val gvmVersionMajor =
requireNotNull(graalVm.get().version.split(".").first().toIntOrNull()) {
"Invalid GraalVM JDK version: ${graalVm.get().graalVmJdkVersion}"
}
if (gvmVersionMajor < 24) {
execOperations.exec {
val executableName = if (os.isWindows) "gu.cmd" else "gu"
executable = distroBinDir.resolve(executableName).toString()
args("install", "--no-progress", "native-image")
}
}
println("Creating symlink ${graalVm.get().installDir} for $distroDir")
val tempLink = Paths.get(graalVm.get().homeDir, UUID.randomUUID().toString())
Files.createSymbolicLink(tempLink, distroDir)
try {
Files.move(tempLink, graalVm.get().installDir.toPath(), StandardCopyOption.ATOMIC_MOVE)
} catch (e: Exception) {
try {
fileOperations.delete(tempLink.toFile())
} catch (ignored: Exception) {}
throw e
}
} catch (e: Exception) {
try {
fileOperations.delete(distroDir)
} catch (ignored: Exception) {}
throw e
}
}
}

View File

@@ -1,64 +0,0 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:Suppress("MemberVisibilityCanBePrivate")
import java.util.*
import org.gradle.jvm.toolchain.JavaLanguageVersion
typealias JavaVersionPair = Pair<JavaLanguageVersion, JavaLanguageVersion>
// All LTS releases.
private val ltsReleases =
sortedSetOf(
JavaLanguageVersion.of(8),
JavaLanguageVersion.of(11),
JavaLanguageVersion.of(17),
JavaLanguageVersion.of(21),
)
/** Describes an inclusive range of JVM versions, based on the [JavaLanguageVersion] type. */
@JvmInline
value class JavaVersionRange private constructor(private val bounds: JavaVersionPair) :
Iterable<JavaLanguageVersion> {
@Suppress("unused")
companion object {
fun isLTS(version: JavaLanguageVersion): Boolean = version in ltsReleases
fun inclusive(floor: JavaLanguageVersion, ceiling: JavaLanguageVersion): JavaVersionRange =
JavaVersionRange(floor to ceiling)
fun startingAt(floor: JavaLanguageVersion): JavaVersionRange =
inclusive(floor, JavaLanguageVersion.of(PKL_TEST_JDK_MAXIMUM))
fun upTo(ceiling: JavaLanguageVersion): JavaVersionRange =
inclusive(JavaLanguageVersion.of(PKL_TEST_JDK_MINIMUM), ceiling)
}
operator fun contains(version: JavaLanguageVersion): Boolean =
version >= bounds.first && version <= bounds.second
fun asSequence(): Sequence<JavaLanguageVersion> = sequence {
var current = bounds.first
while (current <= bounds.second) {
yield(current)
current = JavaLanguageVersion.of(current.asInt() + 1)
}
}
fun asSortedSet(): SortedSet<JavaLanguageVersion> = asSequence().toSortedSet()
override fun iterator(): Iterator<JavaLanguageVersion> = asSortedSet().iterator()
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -111,7 +111,7 @@ open class MergeSourcesJars : DefaultTask() {
relocatedPkgs: Map<String, String>,
details: FileVisitDetails,
sourceText: String,
importPattern: Pattern,
importPattern: Pattern
): String {
val matcher = importPattern.matcher(sourceText)
val buffer = StringBuffer()

View File

@@ -15,7 +15,6 @@
*/
import com.diffplug.gradle.spotless.KotlinGradleExtension
import org.gradle.accessors.dm.LibrariesForLibs
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { id("com.diffplug.spotless") }
@@ -42,15 +41,6 @@ configurations {
}
}
configurations.all {
resolutionStrategy.eachDependency {
if (requested.group == "org.jetbrains.kotlin") {
// prevent transitive deps from bumping Koltin version
useVersion(libs.versions.kotlin.get())
}
}
}
plugins.withType(JavaPlugin::class).configureEach {
val java = project.extensions.getByType<JavaPluginExtension>()
java.sourceCompatibility = JavaVersion.VERSION_17
@@ -58,9 +48,9 @@ plugins.withType(JavaPlugin::class).configureEach {
}
tasks.withType<KotlinCompile>().configureEach {
compilerOptions {
jvmTarget = JvmTarget.JVM_17
freeCompilerArgs.addAll("-Xjsr305=strict", "-Xjvm-default=all")
kotlinOptions {
jvmTarget = "17"
freeCompilerArgs = freeCompilerArgs + listOf("-Xjsr305=strict", "-Xjvm-default=all")
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,6 +39,9 @@ val firstPartySourcesJarsConfiguration: Configuration =
val relocations =
mapOf(
// pkl-core dependencies
"org.antlr.v4." to "org.pkl.thirdparty.antlr.v4.",
"com.oracle.truffle" to "org.pkl.thirdparty.truffle",
"org.graalvm." to "org.pkl.thirdparty.graalvm.",
"org.organicdesign.fp." to "org.pkl.thirdparty.paguro.",
"org.snakeyaml.engine." to "org.pkl.thirdparty.snakeyaml.engine.",
"org.msgpack." to "org.pkl.thirdparty.msgpack.",
@@ -48,9 +51,6 @@ val relocations =
// pkl-cli dependencies
"org.jline." to "org.pkl.thirdparty.jline.",
"com.github.ajalt.clikt." to "org.pkl.thirdparty.clikt.",
"com.github.ajalt.colormath" to "org.pkl.thirdparty.colormath.",
"com.github.ajalt.mordant" to "org.pkl.thirdparty.mordant",
"com.sun.jna" to "org.pkl.thirdparty.jna",
"kotlin." to "org.pkl.thirdparty.kotlin.",
"kotlinx." to "org.pkl.thirdparty.kotlinx.",
"org.intellij." to "org.pkl.thirdparty.intellij.",
@@ -65,13 +65,13 @@ val relocations =
"io.leangen.geantyref." to "org.pkl.thirdparty.geantyref.",
// pkl-codegen-java dependencies
"com.palantir.javapoet." to "org.pkl.thirdparty.javapoet.",
"com.squareup.javapoet." to "org.pkl.thirdparty.javapoet.",
// pkl-codegen-kotlin dependencies
"com.squareup.kotlinpoet." to "org.pkl.thirdparty.kotlinpoet.",
)
val nonRelocations = listOf("com/oracle/truffle/", "org/graalvm/")
val nonRelocations = listOf("com/oracle/truffle/")
tasks.shadowJar {
inputs.property("relocations", relocations)
@@ -80,28 +80,9 @@ tasks.shadowJar {
configurations = listOf(project.configurations.runtimeClasspath.get())
// not required at runtime / fat JARs can't be used in native-image builds anyway
exclude("org/pkl/cli/svm/**")
exclude("META-INF/maven/**")
exclude("META-INF/upgrade/**")
val info = project.extensions.getByType<BuildInfo>()
val minimumJvmTarget = JavaVersion.toVersion(info.jvmTarget)
manifest.attributes(
// Certain exports need to be added to the Java modulepath for Java 17 to work properly with
// shaded JARs. See the following link for an explanation of this syntax:
// https://bugs.openjdk.org/browse/JDK-8335225
"Add-Exports" to info.jpmsExportsForJarManifest
)
// effectively, this results in calls excluding:
// `META-INF/versions/{18-25}/**`
// at the time of this writing; multi-release JARs beyond JDK 21 break the current
// version of the Shadow plugin, and aren't needed for Truffle's use by Pkl.
JavaVersionRange.startingAt(JavaLanguageVersion.of(minimumJvmTarget.majorVersion.toInt() + 1))
.forEach { exclude("META-INF/versions/${it.asInt()}/**") }
exclude("META-INF/versions/19/**")
// org.antlr.v4.runtime.misc.RuleDependencyProcessor
exclude("META-INF/services/javax.annotation.processing.Processor")

View File

@@ -15,11 +15,20 @@
*/
import de.undercouch.gradle.tasks.download.Download
import de.undercouch.gradle.tasks.download.Verify
import java.nio.file.*
import java.util.UUID
import kotlin.io.path.createDirectories
plugins { id("de.undercouch.download") }
val buildInfo = project.extensions.getByType<BuildInfo>()
val BuildInfo.GraalVm.downloadFile
get(): File {
val extension = if (buildInfo.os.isWindows) "zip" else "tar.gz"
return file(homeDir).resolve("${baseName}.$extension")
}
// tries to minimize chance of corruption by download-to-temp-file-and-move
val downloadGraalVmAarch64 by
tasks.registering(Download::class) { configureDownloadGraalVm(buildInfo.graalVmAarch64) }
@@ -59,16 +68,63 @@ fun Verify.configureVerifyGraalVm(graalvm: BuildInfo.GraalVm) {
algorithm("SHA-256")
}
@Suppress("unused")
// minimize chance of corruption by extract-to-random-dir-and-flip-symlink
val installGraalVmAarch64 by
tasks.registering(InstallGraalVm::class) {
tasks.registering {
dependsOn(verifyGraalVmAarch64)
graalVm = buildInfo.graalVmAarch64
configureInstallGraalVm(buildInfo.graalVmAarch64)
}
@Suppress("unused")
// minimize chance of corruption by extract-to-random-dir-and-flip-symlink
val installGraalVmAmd64 by
tasks.registering(InstallGraalVm::class) {
tasks.registering {
dependsOn(verifyGraalVmAmd64)
graalVm = buildInfo.graalVmAmd64
configureInstallGraalVm(buildInfo.graalVmAmd64)
}
fun Task.configureInstallGraalVm(graalVm: BuildInfo.GraalVm) {
onlyIf { !graalVm.installDir.exists() }
doLast {
val distroDir = Paths.get(graalVm.homeDir, UUID.randomUUID().toString())
try {
distroDir.createDirectories()
println("Extracting ${graalVm.downloadFile} into $distroDir")
// faster and more reliable than Gradle's `copy { from tarTree() }`
exec {
workingDir = file(distroDir)
executable = "tar"
args("--strip-components=1", "-xzf", graalVm.downloadFile)
}
val distroBinDir =
if (buildInfo.os.isMacOsX) distroDir.resolve("Contents/Home/bin")
else distroDir.resolve("bin")
println("Installing native-image into $distroDir")
exec {
val executableName = if (buildInfo.os.isWindows) "gu.cmd" else "gu"
executable = distroBinDir.resolve(executableName).toString()
args("install", "--no-progress", "native-image")
}
println("Creating symlink ${graalVm.installDir} for $distroDir")
val tempLink = Paths.get(graalVm.homeDir, UUID.randomUUID().toString())
Files.createSymbolicLink(tempLink, distroDir)
try {
Files.move(tempLink, graalVm.installDir.toPath(), StandardCopyOption.ATOMIC_MOVE)
} catch (e: Exception) {
try {
delete(tempLink.toFile())
} catch (ignored: Exception) {}
throw e
}
} catch (e: Exception) {
try {
delete(distroDir)
} catch (ignored: Exception) {}
throw e
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,23 +27,20 @@ tasks.addRule("Pattern: compatibilityTest[All|Releases|Latest|Candidate|Nightly|
dependsOn(
"compatibilityTestReleases",
"compatibilityTestCandidate",
"compatibilityTestNightly",
"compatibilityTestNightly"
)
}
// releases in configured range
"Releases" ->
task("compatibilityTestReleases") {
val versionInfos = GradleVersionInfo.fetchReleases()
val allVersions =
versionInfos
.filter { versionInfo ->
val v = versionInfo.gradleVersion
!versionInfo.broken &&
v in gradlePluginTests.minGradleVersion..gradlePluginTests.maxGradleVersion &&
v !in gradlePluginTests.skippedGradleVersions
}
.sortedBy { it.gradleVersion }
val versionsToTestAgainst = listOf(allVersions.first(), allVersions.last())
val versionsToTestAgainst =
versionInfos.filter { versionInfo ->
val v = versionInfo.gradleVersion
!versionInfo.broken &&
v in gradlePluginTests.minGradleVersion..gradlePluginTests.maxGradleVersion &&
v !in gradlePluginTests.skippedGradleVersions
}
dependsOn(versionsToTestAgainst.map { createCompatibilityTestTask(it) })
}
@@ -82,16 +79,16 @@ tasks.addRule("Pattern: compatibilityTest[All|Releases|Latest|Candidate|Nightly|
else ->
createCompatibilityTestTask(
taskNameSuffix,
"https://services.gradle.org/distributions-snapshots/gradle-$taskNameSuffix-bin.zip",
"https://services.gradle.org/distributions-snapshots/gradle-$taskNameSuffix-bin.zip"
)
}
}
fun createCompatibilityTestTask(versionInfo: GradleVersionInfo): TaskProvider<Test> =
fun createCompatibilityTestTask(versionInfo: GradleVersionInfo): Task =
createCompatibilityTestTask(versionInfo.version, versionInfo.downloadUrl)
fun createCompatibilityTestTask(version: String, downloadUrl: String): TaskProvider<Test> {
return tasks.register("compatibilityTest$version", Test::class.java) {
fun createCompatibilityTestTask(version: String, downloadUrl: String): Task {
return tasks.create("compatibilityTest$version", Test::class.java) {
mustRunAfter(tasks.test)
maxHeapSize = tasks.test.get().maxHeapSize

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,39 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:Suppress("HttpUrlsUsage", "unused")
@file:Suppress("HttpUrlsUsage")
import org.gradle.accessors.dm.LibrariesForLibs
plugins {
`java-library`
`jvm-toolchains`
id("pklKotlinTest")
id("com.diffplug.spotless")
}
// make sources Jar available to other subprojects
val sourcesJarConfiguration: Provider<Configuration> = configurations.register("sourcesJar")
val sourcesJarConfiguration = configurations.register("sourcesJar")
// Version Catalog library symbols.
val libs = the<LibrariesForLibs>()
// Build configuration.
val info = project.extensions.getByType<BuildInfo>()
java {
val jvmTarget = JavaVersion.toVersion(info.jvmTarget)
withSourcesJar() // creates `sourcesJar` task
withJavadocJar()
sourceCompatibility = jvmTarget
targetCompatibility = jvmTarget
toolchain {
languageVersion = info.jdkToolchainVersion
vendor = info.jdkVendor
}
}
artifacts {
@@ -70,11 +56,7 @@ tasks.compileKotlin { enabled = false }
tasks.jar {
manifest {
attributes +=
mapOf(
"Automatic-Module-Name" to "org.${project.name.replace("-", ".")}",
"Add-Exports" to info.jpmsExportsForJarManifest,
)
attributes += mapOf("Automatic-Module-Name" to "org.${project.name.replace("-", ".")}")
}
}
@@ -98,48 +80,9 @@ val workAroundKotlinGradlePluginBug by
}
}
val truffleJavacArgs =
listOf(
// TODO: determine correct limits for Truffle specializations
// (see https://graalvm.slack.com/archives/CNQSB2DHD/p1712380902746829)
"-Atruffle.dsl.SuppressWarnings=truffle-limit"
)
tasks.compileJava {
javaCompiler = info.javaCompiler
dependsOn(workAroundKotlinGradlePluginBug)
options.compilerArgs.addAll(truffleJavacArgs + info.jpmsAddModulesFlags)
// TODO: determine correct limits for Truffle specializations
// (see https://graalvm.slack.com/archives/CNQSB2DHD/p1712380902746829)
options.compilerArgs.add("-Atruffle.dsl.SuppressWarnings=truffle-limit")
}
tasks.withType<JavaCompile>().configureEach {
val jvmTarget = JavaVersion.toVersion(info.jvmTarget)
javaCompiler = info.javaCompiler
sourceCompatibility = jvmTarget.majorVersion
targetCompatibility = jvmTarget.majorVersion
}
tasks.withType<JavaExec>().configureEach { jvmArgs(info.jpmsAddModulesFlags) }
fun Test.configureJdkTestTask(launcher: Provider<JavaLauncher>) {
useJUnitPlatform()
javaLauncher = launcher
systemProperties.putAll(info.testProperties)
jvmArgs.addAll(info.jpmsAddModulesFlags)
}
tasks.test { configureJdkTestTask(info.javaTestLauncher) }
// Prepare test tasks for each JDK version which is within the test target suite for Pkl. Each task
// uses a pinned JDK toolchain version, and is named for the major version which is tested.
//
// Test tasks configured in this manner are executed manually by name, e.g. `./gradlew testJdk11`,
// and automatically as dependencies of `check`.
//
// We omit the current JDK from this list because it is already tested, in effect, by the default
// `test` task.
//
// Pkl subprojects may elect to further configure these tasks as needed; by default, each task
// inherits the configuration of the default `test` task (aside from an overridden launcher).
val jdkTestTasks = info.multiJdkTestingWith(tasks.test) { (_, jdk) -> configureJdkTestTask(jdk) }
if (info.multiJdkTesting) tasks.check { dependsOn(jdkTestTasks) }

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,13 @@
* limitations under the License.
*/
import org.gradle.accessors.dm.LibrariesForLibs
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
plugins {
id("pklJavaLibrary")
kotlin("jvm")
}
// Build configuration.
val buildInfo = project.extensions.getByType<BuildInfo>()
// Version Catalog library symbols.
@@ -40,7 +38,3 @@ dependencies {
tasks.compileKotlin {
enabled = true // disabled by pklJavaLibrary
}
tasks.withType<KotlinJvmCompile>().configureEach {
compilerOptions { jvmTarget = JvmTarget.fromTarget(buildInfo.jvmTarget.toString()) }
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,7 @@
import java.net.URI
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
plugins {
`jvm-test-suite`
kotlin("jvm")
}
plugins { kotlin("jvm") }
val buildInfo = project.extensions.getByType<BuildInfo>()

View File

@@ -1,6 +1,6 @@
name: main
title: Main Project
version: 0.28.0
version: 0.27.2
prerelease: false
nav:
- nav.adoc

View File

@@ -3,44 +3,35 @@
# This file is expected to be part of source control.
com.tunnelvisionlabs:antlr4-runtime:4.9.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
io.leangen.geantyref:geantyref:1.3.16=testRuntimeClasspath
net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.14.18=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.27.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.polyglot:polyglot:24.1.2=testRuntimeClasspath
org.graalvm.sdk:collections:24.1.2=testRuntimeClasspath
org.graalvm.sdk:graal-sdk:24.1.2=testRuntimeClasspath
org.graalvm.sdk:nativeimage:24.1.2=testRuntimeClasspath
org.graalvm.sdk:word:24.1.2=testRuntimeClasspath
org.graalvm.truffle:truffle-api:24.1.2=testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-build-tools-impl:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-compiler-runner:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-daemon-client:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:2.0.21=kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-native-prebuilt:2.0.21=kotlinNativeBundleConfiguration
org.jetbrains.kotlin:kotlin-reflect:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-script-runtime:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-scripting-common:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-jvm:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.0.21=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.0.21=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains:annotations:13.0=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-engine:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.platform:junit-platform-engine:1.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit:junit-bom:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:23.0.6=testRuntimeClasspath
org.graalvm.truffle:truffle-api:23.0.6=testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.7.10=kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-reflect:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-script-runtime:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-scripting-common:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-jvm:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains:annotations:13.0=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-engine:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-params:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.platform:junit-platform-engine:1.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit:junit-bom:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.msgpack:msgpack-core:0.9.8=testRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.organicdesign:Paguro:3.10.3=testRuntimeClasspath
org.snakeyaml:snakeyaml-engine:2.9=testRuntimeClasspath
org.snakeyaml:snakeyaml-engine:2.5=testRuntimeClasspath
empty=annotationProcessor,apiDependenciesMetadata,compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtimeClasspath,runtimeOnlyDependenciesMetadata,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions

View File

@@ -1,20 +0,0 @@
= Evolution and Roadmap
:uri-pkl-roadmap: https://github.com/orgs/apple/projects/12/views/1
:uri-pkl-evolution: https://github.com/apple/pkl-evolution
== Evolution
Sometimes, a change to Pkl is large enough that it makes sense to create a proposal for the change so that it can be discussed in detail and vetted.
Pkl has a process for managing such designs in a repository called {uri-pkl-evolution}[Pkl Evolutiuon].
== Roadmap
To discover what might be coming in future versions, reference the {uri-pkl-roadmap}[Pkl Roadmap] project on GitHub.
The roadmap describes estimates.
The Pkl team aims to cut a release in February, June, and October of each year.
If an item is not complete by the release cutoff date, the roadmap item may be bumped to the next release.
Additionally, as priorities change, it is possible that items can be moved around, or backlogged.

View File

@@ -3,7 +3,7 @@
// the following attributes must be updated immediately before a release
// pkl version corresponding to current git commit without -dev suffix or git hash
:pkl-version-no-suffix: 0.28.0
:pkl-version-no-suffix: 0.27.2
// tells whether pkl version corresponding to current git commit
// is a release version (:is-release-version: '') or dev version (:!is-release-version:)
:is-release-version: ''
@@ -71,7 +71,6 @@ endif::[]
:uri-stdlib-analyzeModule: {uri-pkl-stdlib-docs}/analyze
:uri-stdlib-jsonnetModule: {uri-pkl-stdlib-docs}/jsonnet
:uri-stdlib-reflectModule: {uri-pkl-stdlib-docs}/reflect
:uri-stdlib-mathModule: {uri-pkl-stdlib-docs}/math
:uri-stdlib-xmlModule: {uri-pkl-stdlib-docs}/xml
:uri-stdlib-protobufModule: {uri-pkl-stdlib-docs}/protobuf
:uri-stdlib-evaluatorSettingsModule: {uri-pkl-stdlib-docs}/EvaluatorSettings
@@ -143,5 +142,3 @@ endif::[]
:uri-messagepack: https://msgpack.org/index.html
:uri-messagepack-spec: https://github.com/msgpack/msgpack/blob/master/spec.md
:uri-pkl-roadmap: https://github.com/orgs/apple/projects/12/views/1

View File

@@ -75,7 +75,7 @@ requestId: Int
/// API version of the CLI's `--allowed-modules` flag
allowedModules: Listing<String>?
/// Regex patterns to determine which resources are allowed to be read.
/// Regex patterns to dettermine which resources are allowed to be read.
///
/// API version of the CLI's `--allowed-resources` flag
allowedResources: Listing<String>?
@@ -130,7 +130,7 @@ class ClientResourceReader {
/// The URI scheme this reader is responsible for reading.
scheme: String
/// Tells whether the path part of this URI has a
/// Tells whether the path part of ths URI has a
/// [hier-part](https://datatracker.ietf.org/doc/html/rfc3986#section-3).
///
/// An example of a hierarchical URI is `file:///path/to/my/file`, where
@@ -148,7 +148,7 @@ class ClientModuleReader {
/// The URI scheme this reader is responsible for reading.
scheme: String
/// Tells whether the path part of this URI has a
/// Tells whether the path part of ths URI has a
/// [hier-part](https://datatracker.ietf.org/doc/html/rfc3986#section-3).
///
/// An example of a hierarchical URI is `file:///path/to/my/file`, where
@@ -427,7 +427,7 @@ evaluatorId: Int
/// The contents of the resource.
contents: Binary? // <1>
/// The description of the error that occurred when reading this resource.
/// The description of the error that occured when reading this resource.
error: String?
typealias Binary = Any // <1>
@@ -478,7 +478,7 @@ evaluatorId: Int
/// The string contents of the module.
contents: String?
/// The description of the error that occurred when reading this resource.
/// The description of the error that occured when reading this resource.
error: String?
----
@@ -528,7 +528,7 @@ evaluatorId: Int
/// The elements at the provided base path.
pathElements: Listing<PathElement>?
/// The description of the error that occurred when listing elements.
/// The description of the error that occured when listing elements.
error: String?
class PathElement {
@@ -586,7 +586,7 @@ evaluatorId: Int
/// The elements at the provided base path.
pathElements: Listing<PathElement>?
/// The description of the error that occurred when listing elements.
/// The description of the error that occured when listing elements.
error: String?
class PathElement {

View File

@@ -1,6 +1,6 @@
= Java Code Generator
include::ROOT:partial$component-attributes.adoc[]
:uri-pkl-codegen-java-maven-module: {uri-maven-docsite}/artifact/org.pkl-lang/pkl-codegen-java
:uri-pkl-codgen-java-maven-module: {uri-maven-docsite}/artifact/org.pkl-lang/pkl-codegen-java
The Java source code generator takes Pkl class definitions as an input, and generates corresponding Java classes with equally named properties.
@@ -23,7 +23,7 @@ See xref:pkl-gradle:index.adoc#installation[Installation] in the Gradle plugin c
[[install-library]]
=== Java Library
The `pkl-codegen-java` library is available {uri-pkl-codegen-java-maven-module}[from Maven Central].
The `pkl-codegen-java` library is available {uri-pkl-codgen-java-maven-module}[from Maven Central].
It requires Java 17 or higher.
ifndef::is-release-version[]
@@ -145,27 +145,23 @@ Flag that indicates to generate private final fields and public getter methods i
[%collapsible]
====
Default: (flag not set) +
Flag that indicates to preserve Pkl doc comments by generating corresponding Javadoc comments.
Flag that indicates to generate Javadoc based on doc comments for Pkl modules, classes, and properties.
====
.--params-annotation
[%collapsible]
====
Default: `none` if `--generate-spring-boot` is set, `org.pkl.config.java.mapper.Named` otherwise +
Fully qualified name of the annotation type to use for annotating constructor parameters with their name. +
The specified annotation type must have a `value` parameter of type `String` or the generated code may not compile.
If set to `none`, constructor parameters are not annotated.
Whether and how constructor parameters should be annotated depends on the library that instantiates the generated classes.
For Spring Boot applications, and for users of `pkl-config-java` compiling the generated classes with `-parameters`, no annotation is required.
Default: `org.pkl.config.java.mapper.Named` +
Fully qualified name of the annotation to use on constructor parameters.
====
.--non-null-annotation
[%collapsible]
====
Default: `org.pkl.config.java.mapper.NonNull` +
Fully qualified name of the annotation type to use for annotating non-null types. +
The specified annotation type must be annotated with `@java.lang.annotation.Target(ElementType.TYPE_USE)`
or the generated code may not compile.
Fully qualified named of the annotation class to use for non-null types. +
This annotation is required to have `java.lang.annotation.ElementType.TYPE_USE` as a `@Target`
or it may generate code that does not compile.
====
Common code generator options:

View File

@@ -26,7 +26,7 @@ Flag that indicates to generate config classes for use with Spring Boot.
[%collapsible]
====
Default: (not set) +
Flag that indicates to generate classes that implement `java.io.Serializable`.
Whether to make generated classes implement `java.io.Serializable`.
====
.--rename

View File

@@ -118,7 +118,7 @@ Relative URIs are resolved against the working directory.
[%collapsible]
====
Default: (flag not set) +
Flag that indicates to preserve Pkl doc comments by generating corresponding KDoc comments.
Flag that indicates to generate Kdoc based on doc comments for Pkl modules, classes, and properties.
====
Common code generator options:

View File

@@ -2,11 +2,13 @@
include::ROOT:partial$component-attributes.adoc[]
:uri-common-mark: https://commonmark.org/
:uri-newspeak: https://newspeaklanguage.org
:uri-antlr4: https://www.antlr.org
:uri-prototypical-inheritance: https://en.wikipedia.org/wiki/Prototype-based_programming
:uri-double-precision: https://en.wikipedia.org/wiki/Double-precision_floating-point_format
:uri-progressive-disclosure: https://en.wikipedia.org/wiki/Progressive_disclosure
:uri-javadoc-Pattern: https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html
:uri-github-PklLexer: {uri-github-tree}/pkl-core/src/main/java/org/pkl/core/parser/Lexer.java
:uri-github-PklLexer: {uri-github-tree}/pkl-core/src/main/antlr/PklLexer.g4
:uri-github-PklParser: {uri-github-tree}/pkl-core/src/main/antlr/PklParser.g4
:uri-pkl-core-ModuleSchema: {uri-pkl-core-main-sources}/ModuleSchema.java
:uri-pkl-core-SecurityManager: {uri-pkl-core-main-sources}/SecurityManager.java
:uri-pkl-core-ResourceReader: {uri-pkl-core-main-sources}/resource/ResourceReader.java
@@ -2034,9 +2036,6 @@ greeting2 = greetPigeon(parrot) // <4>
<3> Call instance method on `pigeon`.
<4> Call module method (on `this`).
Like other object-oriented languages, methods defined on extended classes and modules may be overridden.
The parent type's method may be called via the <<super-keyword,`super` keyword>>.
NOTE: Methods do not support named parameters or default parameter values.
The xref:blog:ROOT:class-as-a-function.adoc[Class-as-a-function] pattern may be a suitable replacement.
@@ -2574,7 +2573,7 @@ the following security checks are performed:
* The target module URI is checked against the module allowlist (`--allowed-modules`).
* The source and target modules' _trust levels_ are determined and compared.
For access to be granted, the source module's trust level must be greater than or equal to the target module's trust level.
For access to be granted, the source module's trust level must be higher than or equal to the target module's trust level.
By default, there are five trust levels, listed from highest to lowest:
. `repl:` modules (code evaluated in the REPL)
@@ -2717,7 +2716,7 @@ quota:
disk: 20 GB
----
In addition to _class_-based converters, renderers also support _path_-based converters:
In addition to _type_ based converters, renderers also support _path_ based converters:
[source%parsed,{pkl}]
----
@@ -3194,13 +3193,10 @@ This section discusses language features that are generally more relevant to tem
<<for-generators,For Generators>> +
<<spread-syntax,Spread Syntax>> +
<<member-predicates,Member Predicates (`[[...]]`)>> +
<<this-keyword,`this` Keyword>> +
<<outer-keyword,`outer` Keyword>> +
<<super-keyword,`super` Keyword>> +
<<module-keyword,`module` Keyword>> +
<<glob-patterns,Glob Patterns>> +
<<doc-comments,Doc Comments>> +
<<name-resolution,Name Resolution>> +
<<grammar-definition,Grammar Definition>> +
<<reserved-keywords,Reserved Keywords>> +
<<blank-identifiers,Blank Identifiers>> +
<<projects,Projects>> +
@@ -3357,9 +3353,9 @@ swiftHatchlings = typedProperty.listHatchlings(new { "Poppy"; "Chirpy" }) // <8>
<2> Assignment to an undeclared property in module context, amending `new Dynamic {}`.
<3> `Listing` element creation, amending implicit `default`, `new Bird {}`.
<4> `Listing` element creation, amending implicit `default`, `new Dynamic {}`.
<5> `Mapping` value assignment, amending the result of applying `default` to `"Saltmarsh Sparrow"`, `new Bird { name = "Saltmarsh Sparrow" }`.
<5> `Mapping` value assignment, amdending the result of applying `default` to `"Saltmarsh Sparrow"`, `new Bird { name = "Saltmarsh Sparrow" }`.
<6> `Mapping` value assignment _replacing_ the parent's entry, amending the result of applying `default` to `"Saltmarsh Sparrow"`, `new Bird { name = "Saltmarsh Sparrow" }`.
<7> Amending the property default value `new Listing { new Bird { name = "Osprey" } }`; the result contains both birds.
<7> Admending the property default value `new Listing { new Bird { name = "Osprey" } }`; the result contains both birds.
<8> Error: Cannot tell which parent to amend.
[[let-expressions]]
@@ -3543,7 +3539,9 @@ res6 = list.map((n) -> n * 3) // <6>
[[sets]]
=== Sets
A value of type link:{uri-stdlib-Set}[Set] is a collection of unique _elements_.
A value of type link:{uri-stdlib-Set}[Set] is an ordered collection of unique _elements_.
A set's elements are eagerly evaluated.
Sets are constructed with the `Set()` methodfootnote:soft-keyword[]:
@@ -3559,20 +3557,6 @@ res4 = Set(1, "x", 5.min, List(1, 2, 3)) // <4>
<3> result: same set of length 3
<4> result: heterogeneous set that contains a list as its last element
Sets retain the order of elements when constructed, which impacts how they are iterated over.
However, this order is not considered when determining equality of two sets.
[source%tested,{pkl}]
----
res1 = Set(4, 3, 2)
res2 = res1.first // <1>
res3 = res1.toListing() // <2>
res4 = Set(2, 3, 4) == res1 // <3>
----
<1> result: `4`
<2> result: `new Listing { 4; 3; 2 }`
<3> result: `true`
To compute the union of sets, use the `+` operator:
[source%tested,{pkl-expr}]
@@ -3600,7 +3584,7 @@ res4 = set.intersect(Set(3, 9, 2)) // <4>
[[maps]]
=== Maps
A value of type link:{uri-stdlib-Map}[Map] is a collection of _values_ indexed by _key_.
A value of type link:{uri-stdlib-Map}[Map] is an ordered collection of _values_ indexed by _key_.
A map's key-value pairs are called its _entries_.
Keys and values are eagerly evaluated.
@@ -3635,20 +3619,6 @@ Any Pkl value can be used as a map key:
Map(new Dynamic { name = "Pigeon" }, 10.gb)
----
Maps retain the order of entries when constructed, which impacts how they are iterated over.
However, this order is not considered when determining equality of two maps.
[source%tested,{pkl}]
----
res1 = Map(2, "hello", 1, "world")
res2 = res1.entries.first // <1>
res3 = res1.toMapping() // <2>
res4 = res1 == Map(1, "world", 2, "hello") // <3>
----
<1> result: `Pair(2, "hello")`
<2> result: `new Mapping { [2] = "hello"; [1] = "world" }`
<3> result: `true`
To merge maps, use the `+` operator:
[source%tested,{pkl}]
@@ -4833,161 +4803,6 @@ The predicate, enclosed in double brackets (`\[[...]]`), is matched against each
Within the predicate, `this` refers to the member that the predicate is matched against.
Matching members are amended (`{ ... }`) or overridden (`= <new-value>`).
[[this-keyword]]
=== `this` keyword
Normally, the `this` keyword references the enclosing object's receiver.
Example:
[source,pkl]
----
bird {
eatsInsects = this is InsectavorousBird
}
----
When used inside a <<type-constraints,type constraint>>, `this` refers to the value being tested.
Example:
[source,pkl]
----
port: UInt16(this > 1000)
----
When used inside a <<member-predicates,member predicate>>, `this` refers to the value being matched against.
Example:
[source,pkl]
----
animals {
[[this is Bird]] {
canFly = true
}
}
----
[[receiver]]
==== Receiver
The receiver is the bottom-most object in the <<prototype-chain>>.
That means that, within the context of an amending object, the reciever is the amending object.
Example:
[source,pkl]
----
hidden lawyerBird {
title = "\(this.name), Esq."
}
polly = (lawyerBird) {
name = "Polly" // <1>
}
----
<1> Polly has title `"Polly, Esq."`.
[[outer-keyword]]
=== `outer` keyword
The `outer` keyword references the <<receiver,receiver>> of the immediately outer lexical object.
It can be useful to disambiguate a lookup that might otherwise resolve elsewhere.
Example:
[source%tested,pkl]
----
foo {
bar = "bar"
qux {
bar = outer.bar // <1>
}
}
----
<1> References `bar` one level higher.
Note that `outer` cannot be chained.
In order to reference a value more than one level higher, a typical pattern is to declare a local property at that level.
For example:
[source%parsed,pkl]
----
foo {
local self = this
bar {
baz {
qux = self.qux
}
}
}
----
[[super-keyword]]
=== `super` keyword
The `super` keyword references the parent object in the <<prototype-chain,prototype chain>>.
When used within a class, it refers to the superclass's prototype.
When used within an object, it refers to the parent object in the amends chain.
Example:
[source%tested,pkl]
----
bird = new { name = "Quail" }
bird2 = (bird) { name = "Ms. \(super.name)" } // <1>
abstract class Bird {
foods: Listing<String>
function canEat(food: String): Boolean = foods.contains(food)
}
class InsectavorousBird extends Bird {
function canEat(food: String) =
super.canEat(food) || food == "insect" // <2>
}
----
<1> Result: `"Ms. Quail"`
<2> Calls parent class method `canEat()`
The `super` keyword must be followed by property/method access, or subscript.
`super` by itself a syntax error; whereas `super.foo` and `super["foo"]` are valid expressions.
[[module-keyword]]
=== `module` keyword
The `module` keyword can be used as either a value, or as a type.
When used as a value, it refers to the <<receiver,receiver>> of the module itself.
[source%tested,pkl]
----
name = "Quail"
some {
deep {
object {
name = module.name // <1>
}
}
}
----
<1> Resolves to `"Quail"`
When used as a type, it is the module's class.
[source%parsed,pkl]
----
module Bird
friend: module // <1>
----
<1> Is class `Bird`
The `module` type is a _self type_.
If the module is extended by another module, the `module` type refers to the extending module when
in the context of that module.
[[glob-patterns]]
=== Glob Patterns
@@ -5074,8 +4889,8 @@ TIP: If incorporating escape characters into a glob pattern, use <<custom-string
|===
|Pattern |Description
|`*.pk[lg]`
|Anything suffixed by `.pkl`, or `.pkg`.
|`*.pc[lf]`
|Anything suffixed by `.pkl`, or `.pcf`.
|`**.y{a,}ml`
|Anything suffixed by either `yml` or `yaml`, crossing directory boundaries.
@@ -5433,6 +5248,11 @@ For example, the prototype chain of value `42` contains, now listed from top to
A prototype chain never contains a non-object value, such as `42`.
[[grammar-definition]]
=== Grammar Definition
Pkl's link:{uri-antlr4}[ANTLR 4] grammar is defined in link:{uri-github-PklLexer}[PklLexer.g4] and link:{uri-github-PklParser}[PklParser.g4].
[[reserved-keywords]]
=== Reserved keywords
@@ -5449,8 +5269,6 @@ They cannot be used as a regular identifier, and currently do not have any meani
To use these names in an identifier, <<quoted-identifiers, surround them with backticks>>.
For a complete list of keywords, consult field `Lexer.KEYWORDS` in {uri-github-PklLexer}[Lexer.java].
[[blank-identifiers]]
=== Blank Identifiers
@@ -5657,7 +5475,7 @@ Readers are implemented as ordinary executables and use Pkl's xref:bindings-spec
The xref:swift:ROOT:index.adoc[Swift] and xref:go:ROOT:index.adoc[Go] language binding libraries provide an `ExternalReaderRuntime` type to facilitate implementing external readers.
External readers are configured separately for modules and resources.
They are registered by mapping their URI scheme to the executable to run and additional arguments to pass.
They are registered by mapping their URI scheme to the executable to run and additonal arguments to pass.
This is done on the command line by passing `--external-resource-reader` and `--external-module-reader` flags, which may both be passed multiple times.
[source,text]

View File

@@ -134,7 +134,6 @@ exampleObjectWithMixedElements {
<2> Elements don't have to be literal values; they can be arbitrary _expressions_.
<3> Elements can really be _any_ value, not just primitive values.
[[entries]]
=== Entries
Objects can have one more kind of member; _entries_.

View File

@@ -213,7 +213,7 @@ adultBirdFoods {
A `.pkl` file describes a _module_.
Modules are objects that can be referred to from other modules.
Going back to the example above, you can write `pigeon` as a separate module.
Going back to the example above, you can write `parrot` as a separate module.
[source,{pkl}]
.pigeon.pkl

View File

@@ -53,7 +53,8 @@ whereas, the Alpine Linux executable is statically linked against _musl libc_ an
====
The Java executable works on multiple platforms and has a smaller binary size than the native executables.
However, it requires a Java 17 (or higher) runtime on the system path, and has a noticeable startup delay.
However, it requires a Java 17 (or higher) runtime on the system path, has a noticeable startup delay,
and runs complex Pkl code slower than the native executables.
All flavors are built from the same codebase and undergo the same automated testing.
Except where noted otherwise, the rest of this page discusses the native executables.
@@ -200,14 +201,6 @@ NOTE: We currently do not support the aarch64 architecture for Windows.
[[java-executable]]
=== Java Executable
The Java executable is a jar that can be executed directly on macOS, Linux, and Windows.
It requires `java` to be installed, and available on `$PATH`.
[tabs]
====
macOS/Linux::
+
[source,shell]
[subs="+attributes"]
----
@@ -216,16 +209,6 @@ chmod +x jpkl
./jpkl --version
----
Windows::
+
[source,PowerShell]
[subs="+attributes"]
----
Invoke-WebRequest '{uri-pkl-java-download}' -OutFile jpkl.bat
.\jpkl --version
----
====
This should print something similar to:
[source,shell]
@@ -234,7 +217,8 @@ This should print something similar to:
Pkl {pkl-version} (macOS 14.2, Java 17.0.10)
----
NOTE: The Java executable is named `jpkl`.
NOTE: The Java executable does not work as an executable file on Windows.
However, it will work as a jar, for example, with `java -jar jpkl`.
[[usage]]
== Usage
@@ -737,6 +721,8 @@ Type :help or :examples for more information.
pkl>
----
NOTE: The Java executable is named `jpkl`.
=== Loading Modules
To load <<config.pkl,`config.pkl`>> into the REPL, run:

View File

@@ -232,18 +232,10 @@ Relative URIs are resolved against the working directory.
[%collapsible]
====
Default: (none) +
Example: `pkldoc` +
Example: `pkldoc`
The directory where generated documentation is placed.
====
.--no-symlinks
[%collapsible]
====
Create copies of files and directories instead of symbolic links.
In particular, this affects how the "current" directories containing documentation content for the last generated version should be created.
By default, a symbolic link is created pointing to the last generated version. If symlinks are disabled, a full copy of the last generated version is created.
====
Common CLI options:
include::../../pkl-cli/partials/cli-common-options.adoc[]

View File

@@ -373,26 +373,14 @@ Example: `generateGetters = true` +
Whether to generate private final fields and public getter methods rather than public final fields.
====
.paramsAnnotation: Property<String>
// TODO: fixme (paramsAnnotation, nonNullAnnotation)
.preferJavaxInjectAnnotation: Boolean
[%collapsible]
====
Default: `null` if `generateSpringBootConfig` is `true`, `"org.pkl.config.java.mapper.Named"` otherwise+
Example: `paramsAnnotation = "org.project.MyAnnotation"` +
Fully qualified name of the annotation type to use for annotating constructor parameters with their name. +
The specified annotation type must have a `value` parameter of type `String` or the generated code may not compile.
If set to `null`, constructor parameters are not annotated.
Whether and how constructor parameters should be annotated depends on the library that instantiates the generated classes.
For Spring Boot applications, and for users of `pkl-config-java` compiling the generated classes with `-parameters`, no annotation is required.
====
.nonNullAnnotation: Property<String>
[%collapsible]
====
Default: `"org.pkl.config.java.mapper.NonNull"` +
Example: `nonNullAnnotation = "org.project.MyAnnotation"` +
Fully qualified name of the annotation type to use for annotating non-null types. +
The specified annotation type must be annotated with `@java.lang.annotation.Target(ElementType.TYPE_USE)`
or the generated code may not compile.
Default: `false` +
Example: `preferJavaxInjectAnnotation = true` +
Whether to annotate constructor parameters with `@javax.inject.Named` instead of `@org.pkl.config.java.mapper.Named`.
If `true`, the generated code will have a compile dependency on `javax.inject:javax.inject:1`.
====
Common code generation properties:
@@ -455,15 +443,8 @@ see link:{uri-codegen-kotlin-example}[codegen-kotlin] in the _pkl/pkl-examples_
=== Configuration Options
=== Configuration Options
.generateKdoc: Property<Boolean>
[%collapsible]
====
Default: `false` +
Example: `generateKdoc = true` +
Whether to preserve Pkl doc comments by generating corresponding KDoc comments.
====
// TODO: fixme (generateKdoc)
(None)
Common code generation properties:
@@ -534,17 +515,6 @@ Example: `outputDir = layout.projectDirectory.dir("pkl-docs")` +
The directory where generated documentation is placed.
====
.noSymlinks: Property<Boolean>
[%collapsible]
====
Default: `false` +
Example: `noSymlinks = true` +
Create copies of files and directories instead of symbolic links.
In particular, this affects how the "current" directories containing documentation content for the last generated version should be created.
By default, a symbolic link is created pointing to the last generated version.
If symlinks are disabled, a full copy of the last generated version is created.
====
Common properties:
include::../partials/gradle-modules-properties.adoc[]

View File

@@ -36,14 +36,6 @@ Example: `generateSpringBootConfig = true` +
Whether to generate config classes for use with Spring Boot.
====
.implementSerializable: Property<Boolean>
[%collapsible]
====
Default: `false` +
Example: `implementSerializable = true` +
Whether to generate classes that implement `java.io.Serializable`.
====
.renames: MapProperty<String, String>
[%collapsible]
====
@@ -94,3 +86,4 @@ Keys in this mapping can be arbitrary strings, including an empty string.
Values must be valid dot-separated fully qualifed class name prefixes, possibly terminated by a dot.
====
// TODO: fixme (implementSerializable)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

View File

@@ -12,7 +12,7 @@ This release brings Windows support, improvements to controlling how Pkl talks o
The next release (0.27) is scheduled for October 10th, 2024.
Please send feedback and questions to https://github.com/apple/pkl/discussions[GitHub Discussions], or submit an issue on https://github.com/apple/pkl/issues/new[GitHub]. +
Please send feedback and questions to https://github.com/apple/pkl/discussions[GitHub Discussions], or submit an issue on https://github.com/apple/pkl/issues/new[Github]. +
[small]#Pkl is hosted on https://github.com/apple/pkl[GitHub].
To get started, follow xref:pkl-cli:index.adoc#installation[Installation].#
@@ -460,7 +460,7 @@ To mitigate, the package's version needs to be bumped, even if package contents
== Miscellaneous [small]#🐸#
The following changes have been made that are neither new features nor breaking changes.
The following changes have been made that are not new features, nor breaking changes.
* Pkl's user-agent header for HTTP requests has been tweaked to add a semicolon (https://github.com/apple/pkl/pull/221[#221]). Here is an example difference:
+

View File

@@ -12,7 +12,7 @@ This release brings improvements in typechecking of `Listing` and `Mapping`, the
The next release (0.28) is scheduled for February 2025.
Please send feedback and questions to https://github.com/apple/pkl/discussions[GitHub Discussions], or submit an issue on https://github.com/apple/pkl/issues/new[GitHub]. +
Please send feedback and questions to https://github.com/apple/pkl/discussions[GitHub Discussions], or submit an issue on https://github.com/apple/pkl/issues/new[Github]. +
[small]#Pkl is hosted on https://github.com/apple/pkl[GitHub].
To get started, follow xref:pkl-cli:index.adoc#installation[Installation].#
@@ -121,7 +121,7 @@ A new API has been added to analyze the import graph of Pkl modules (https://git
This API comes in four forms:
1. A standard library module: `pkl:analyze`
2. A CLI command: `pkl analyze imports`
2. A CLI command: `pkl anaylze imports`
3. A Java API: `org.pkl.core.Analyzer`
4. A Gradle API: `org.pkl.gradle.task.AnalyzeImportsTask`

View File

@@ -1,375 +0,0 @@
= Pkl 0.28 Release Notes
:version: 0.28
:version-minor: 0.28.0
:release-date: February 26th, 2025
include::ROOT:partial$component-attributes.adoc[]
:uri-snippet-tests: {uri-github-tree}/pkl-core/src/test/files/LanguageSnippetTests/input
:uri-standard-library: {uri-github-tree}/stdlib/
:uri-antlr: https://www.antlr.org
:wbr: pass:[<wbr />]
Pkl {version} was released on {release-date}. +
[.small]#The latest bugfix release is {version-minor}. (xref:changelog.adoc[All Versions])#
The next release (0.29) is scheduled for June 2025.
To see what's coming in the future, follow the {uri-pkl-roadmap}[Pkl Roadmap].
Please send feedback and questions to https://github.com/apple/pkl/discussions[GitHub Discussions], or submit an issue on https://github.com/apple/pkl/issues/new[GitHub]. +
[small]#Pkl is hosted on https://github.com/apple/pkl[GitHub].
To get started, follow xref:pkl-cli:index.adoc#installation[Installation].#
== Highlights [small]#💖#
News you don't want to miss.
=== New parser
Pkl has new parser (https://github.com/apple/pkl/pull/917[#917], https://github.com/apple/pkl/pull/957[#957], https://github.com/apple/pkl/pull/962[#962])!
The first step to evaluating a program is to parse its source code into a parse tree.
Currently, Pkl uses link:{uri-antlr}[ANTLR] to generate parser code from grammar files.
Using this approach has allowed for rapidly iterating and changing the language's grammar.
However, Pkl's grammar has matured; it's not as likely that the grammar will change from one version to the next.
Additionally, the current parser's performance has become more painful as projects written in Pkl grow in size.
In many cases, parsing can take up most of the time spent during evaluation.
In 0.28, the ANTLR-generated parser is being replaced by a handwritten parser.
In benchmarking tests, this has shown to improve parsing speed by around two orders of magnitude.
Here are some quick comparisons between the two parsers, run on a MacBook Pro M4 Max machine, with 5 warmup iterations, and run for 10 iterations:
|===
||Old parser |New parser
|link:{uri-snippet-tests}[Language snippet tests]
|440.8ms
|5.9ms
|link:{uri-standard-library}[Standard library]
|136.7msfootnote:[In the `pkl` CLI, the standard library is parsed during compilation rather than during evaluation. As a result, there is no parsing overhead.]
|0.8ms
|All https://github.com/apple/pkl-pantry[pkl-pantry] modules
|1424.2ms
|7.0ms
|===
== Noteworthy [small]#🎶#
Ready when you need them.
=== CLI improvements
==== Colored help messages
The `pkl`, `pkldoc`, `pkl-codegen-java`, and `pkl-codegen-kotlin` CLIs now emits help text with colors (https://github.com/apple/pkl/pull/947[#947]).
Here is a sneak peek:
image::pkl-cli-help-new.png[new pkl cli help output]
Thanks to https://github.com/gordonbondon[@gordonbondon] for their contribution!
==== `jpkl` support on Windows
The `jpkl` executable is now supported on Windows (https://github.com/apple/pkl/pull/872[#872]).
`jpkl` is a fat jar that can be executed directly when on macOS and Linux, but current users of Windows are required to execute it with `java -jar <path/to/jpkl>`.
In 0.28, Windows users can also call execute this command directly.
To do so, the filename should be called `jpkl.bat`, and placed in `PATH`.
=== Type constraint changes
Type annotations that are executed as a result of calling a constraint expressions now perform an eager typecheck (https://github.com/apple/pkl/pull/964[#964]).
In Pkl 0.27, we changed how xref:0.27.adoc#typecheck-improvements[typechecks are executed for `Listing` and `Mapping`] types.
However, this had two unintended side effects:
For one, error messages from certain failing constraints show `?` in place of values that are failing.
The following snippet:
[source%parsed,pkl]
----
class Bird { name: String }
bird: Listing<Bird>(firstOneIsQuail) = new {
new { name = "Pigeon" }
new { name = "Quail" }
}
local firstOneIsQuail = (it: Listing<Bird>) -> it[0].name == "Quail"
----
Produces the following error message:
[source]
----
Pkl Error
Type constraint `firstOneIsQuail` violated.
Value: new Listing { ?; ? }
3 | bird: Listing<Bird>(firstOneIsQuail) = new {
^^^^^^^^^^^^^^^
----
:fn-typecheck-details: footnote:[See https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0010-overhauled-mapping-listing-typechecks.adoc#delegating-objects[delegating objects] in SPICE-0010 for more details on this behavior.]
This is happening because lazy typechecks of mappings and listings will return a _new_ listing. Because the lambda's argument is defined as ``it: Listing<Bird>``, the value being passed into the function body is this new listing{fn-typecheck-details}.
Secondly, some constraints became less strict, allowing more values to pass.
The following snippet fails in Pkl 0.26, but passes in Pkl 0.27:
[source%parsed,pkl]
----
class Bird { name: String }
local nonEmpty = (it: Listing<Bird>) -> !it.isEmpty
birds: Listing(nonEmpty) = new { 1; 2; 3 }
----
This is because the function parameter `it: Listing<Bird>` does not actually check members of the argument until they are accessed, and the function body `!it.isEmpty` does not access any members.
To address both of these issues, the rule for executing type constraints has changed.
When executing a type annotation, mapping and listing typechecks are always _eager_.
This means that Pkl will check that each member of the mapping/listing conforms to the type parameter.
=== Java 22+ support
Pkl's Java libraries now support Java 22 and higher (https://github.com/apple/pkl/pull/876[#876]).
Thanks to https://github.com/sgammon[@sgammon] for their contribution!
=== New standard library method
The `pkl:math` standard library module has a new method, called {uri-stdlib-mathModule}/index.html#atan2()[atan2] (https://github.com/apple/pkl/pull/819[#819]).
It computes the https://en.wikipedia.org/wiki/Atan2[2-argument arctangent].
Thanks to https://github.com/gordonbondon[@gordonbondon] for their contribution!
=== Overhauled for-generator implementation
The implementation of xref:language-reference:index.adoc#for-generators[for-generators] has been overhauled (https://github.com/apple/pkl/pull/844[#844]).
This fixes some known bugs with the current for-generator implementation, and also improves code health by reducing complexity and removing workarounds and band-aids.
Thanks to https://github.com/odenix[@odenix] for their contribution!
=== Java code generator improvements
Improvements have been made to the Java code generator (https://github.com/apple/pkl/pull/792[#792]).
In pkl-codegen-java, the `--params-annotation` flag now accepts `none` as a value, which causes the code generator to skip adding annotations to a constructor's parameters.
Additionally, the Kotlin API `org.pkl.codegen.java.JavaCodeGeneratorOptions.paramsAnnotation` is now nullable.
If null, this also skips adding annotations.
By default, this annotation is set to `org.pkl.config.java.mapper.Named`, or none if the `--generate-spring-boot-config` flag is set.
This is useful for those compiling Java code with the `-parameters` flag set, because the pkl-config-java library is able to map into these classes without any extra annotations.
Thanks to https://github.com/odenix[@odenix] for their contribution!
=== Kotlin code generator improvements
Improvements have been made to the Kotlin code generator (https://github.com/apple/pkl/pull/793[#793]).
Currently, the output of `toString()` on a generated Kotlin class differs depending on if it was generated as a data class or as a regular class.
In Pkl 0.28, this method produces the same format, and matches the format used by data classes.
Thanks to https://github.com/odenix[@odenix] for their contribution!
=== pkldoc improvements
pkldoc has a new flag to write real files instead of symlinks (https://github.com/apple/pkl/pull/824[#824]).
Currently, pkldoc creates a symlink called "current", which points to the latest non-prerelease version of a package.
However, these symlinks can be problematic for some systems.
A new flag, `--no-symlinks`, and a similarly named Gradle property, `noSymlinks`, instructs pkldoc to write real files instead of symlinks.
Thanks to https://github.com/netvl[@netvl] for their contributions!
=== `jar:nested:` URIs are accepted by default
To improve integration with Spring Boot, the Pkl evaluator by default now accepts module URIs starting with `jar:nested:` (https://github.com/apple/pkl/pull/895[#895]).
The `--allowed-modules` flag (and the equally named option in other APIs) can be used to configure the set of allowed modules.
== Breaking Changes [small]#💔#
Things to watch out for when upgrading.
=== Stricter grammar
As a result of implementing a new parser, the following previously accepted grammar is no longer valid (https://github.com/apple/pkl/pull/917[#917]).
==== Inline object entries
When declaring multiple xref:language-tutorial:01_basic_config.adoc#entries[entries] on the same line, a semicolon is now required to separate them.
The following code snippet is currently valid, and becomes a syntax error in 0.28.
[source,pkl]
----
obj { ["one"] = 1 ["two"] = 2 }
----
To fix, insert a semicolon between the two entries:
[source,diff]
----
-obj { ["one"] = 1 ["two"] = 2 }
+obj { ["one"] = 1; ["two"] = 2 }
----
==== String escapes
When using xref:language-reference:index.adoc#custom-string-delimiters[custom string delimiters], the escape sequence becomes backslash (`\`) plus the number of pounds used to delimit the string.
Due to a parser bug, any extra pounds after this escape sequence are also permitted.
In Pkl 0.28, this becomes a syntax error.
[source,pkl]
----
foo = "foo \#(bar)" // Invalid character escape sequence `\#`.
----
==== Whitespace between generator members
Inline object spreads, for generators, and when generators all now require either whitespace or a semicolon separator.
[source,pkl]
----
foo { ...bar...baz } // Syntax error
----
=== Minimum Gradle version bump
The minimum Gradle version for the xref:main:pkl-gradle:index.adoc[Gradle Plugin] has been bumped to 8.2 (https://github.com/apple/pkl/pull/901[#901]).
=== Java/Kotlin API breaking changes
Breaking changes have been made to the Java/Kotlin APIs (https://github.com/apple/pkl/pull/748[#748], https://github.com/apple/pkl/pull/749[#749], https://github.com/apple/pkl/pull/776[#776], https://github.com/apple/pkl/pull/793[#793], https://github.com/apple/pkl/pull/808[#808], https://github.com/apple/pkl/pull/810[#810]).
|===
|API |Breakage
| org.pkl.core.resource{wbr}.Resource
| Converted into a record; previous getter methods are deprecated.
| org.pkl.core.project{wbr}.Package
| Converted into a record; previous getter methods are deprecated.
| org.pkl.core.Member{wbr}.SourceLocation
| Converted into a record; previous getter methods are deprecated.
| org.pkl.core{wbr}.Release
| Converted into a record; previous getter methods are deprecated.
| org.pkl.core.Release{wbr}.SourceCode
| Converted into a record; previous getter methods are deprecated.
| org.pkl.core.Release{wbr}.Documentation
| Converted into a record; previous getter methods are deprecated.
| org.pkl.core.Release{wbr}.StandardLibrary
| Converted into a record; previous getter methods are deprecated.
| org.pkl.core.project{wbr}.DeclaredDependencies
| Converted into a record; previous getter methods are deprecated.
| org.pkl.core.evaluatorSettings{wbr}.PklEvaluatorSettings{wbr}.Proxy{wbr}.create
| Deprecated; use the constructor instead.
| org.pkl.core.module{wbr}.ExternalModuleResolver
| Moved into package org.pkl.core.externalreader
| org.pkl.core.resource{wbr}.ExternalResourceResolver
| Moved into package org.pkl.core.externalreader
| org.pkl.core.messaging{wbr}.MessageTransportModuleResolver
| Renamed to ExternalModuleResolverImpl, made package-private
| org.pkl.core.messaging{wbr}.MessageTransportResourceResolver
| Renamed to ExternalResourceResolverImpl, made package-private
| org.pkl.core.module{wbr}.ExternalModuleResolver{wbr}.Spec
| Replaced with record org.pkl.core.externalreader.ModuleReaderSpec
| org.pkl.core.resource{wbr}.ExternalResourceResolver{wbr}.Spec
| Replaced with record org.pkl.core.externalreader.ResourceReaderSpec
| org.pkl.core.messaging{wbr}.CreateEvaluatorRequest
| Changed properties `allowedModules` and `allowedResources` to be of type `List<String>` instead of `List<Pattern>`
| org.pkl.codegen.kotlin{wbr}.KotlinCodegenOptions
| Renamed to org.pkl.codegen.kotlin.KotlinCodeGeneratorOptions
| org.pkl.codegen.kotlin{wbr}.CliKotlinCodeGeneratorOptions{wbr}.toKotlinCodegenOptions
| Deprecated without replacement
| org.pkl.codegen.java{wbr}.JavaCodegenOptions
| Renamed to org.pkl.codegen.java.JavaCodeGeneratorOptions
| org.pkl.codegen.java{wbr}.CliJavaCodeGeneratorOptions{wbr}.toJavaCodegenOptions()
| Deprecated without replacement
|===
=== Fat jars no longer shade Truffle
Pkl publishes two fat jars to Maven Central: https://central.sonatype.com/artifact/org.pkl-lang/pkl-tools[pkl-tools], and https://central.sonatype.com/artifact/org.pkl-lang/pkl-config-java-all[pkl-config-java-all].
Due a version bump in the Truffle library, the package `com.oracle.truffle` can no longer be shaded.
For users that use both Pkl and other Truffle languages, this means that their version of Truffle should match Pkl's version.
== Miscellaneous [small]#🐸#
* Documentation improvements (https://github.com/apple/pkl/pull/792[#792], https://github.com/apple/pkl/pull/846[#846], https://github.com/apple/pkl/pull/860[#860], https://github.com/apple/pkl/pull/892[#892], https://github.com/apple/pkl/pull/921[#921], https://github.com/apple/pkl/pull/937[#937], https://github.com/apple/pkl/pull/943[#943], https://github.com/apple/pkl/pull/944[#944], https://github.com/apple/pkl/pull/955[#955], https://github.com/apple/pkl/pull/956[#956], https://github.com/apple/pkl/pull/973[#973]).
* The repository now requires Java 21 or higher to build (https://github.com/apple/pkl/pull/876[#876]).
* Enable multi-jdk testing via `-DmultiJdkTesting=true` flag when building Pkl (https://github.com/apple/pkl/pull/876[#876]).
* Pkl's version of Kotlin has been upgraded to 2.0 (https://github.com/apple/pkl/pull/900[#900]).
* Allow setting commit id via `-DcommitId` flag when building Pkl (https://github.com/apple/pkl/pull/954[#954]).
== Bugs fixed [small]#🐜#
The following bugs have been fixed.
[smaller]
* Optimization: `const` members should be cached for all children in the prototype chain (https://github.com/apple/pkl/issues/508[#508])
* codegen-kotlin: Use same toString() representation for data classes and regular classes (https://github.com/apple/pkl/issues/717[#717])
* Late-bound values of iteratees within nested for/spread fail to resolve for-generator variables (https://github.com/apple/pkl/issues/741[#741])
* codegen-java/kotlin: Fix generation of equals/hashCode methods (https://github.com/apple/pkl/pull/802[#802])
* Not possible to render mapping with Int keys in YAML (https://github.com/apple/pkl/issues/878[#878])
* Parser accepts wrong string escapes (https://github.com/apple/pkl/issues/888[#888])
* Downstream native-image embedders are broken (https://github.com/apple/pkl/issues/907[#907])
* Failed type constraint error messages do not show forced members (https://github.com/apple/pkl/issues/918[#918])
* ANTLR incompatibilities (https://github.com/apple/pkl/issues/927[#927])
* Doc comments with interleaving comments result in an error (https://github.com/apple/pkl/issues/931[#931])
* Spread elements inside an object body don't need separators (https://github.com/apple/pkl/issues/932[#932])
* Correctly set allowed modules/resoures when external reader scheme contain regex control characters (https://github.com/apple/pkl/pull/941[#941])
* Bad import analysis fails with "None (cause has no message)" (https://github.com/apple/pkl/issues/949[#949])
== Contributors [small]#🙏#
We would like to thank the contributors to this release (in alphabetical order):
* https://github.com/gordonbondon[@gordonbondon]
* https://github.com/HT154[@HT154]
* https://github.com/jsoref[@jsoref]
* https://github.com/KushalP[@KushalP]
* https://github.com/netvl[@netvl]
* https://github.com/odenix[@odenix]
* https://github.com/romacafe[@romacafe]
* https://github.com/sgammon[@sgammon]
* https://github.com/sorcix[@sorcix]
* https://github.com/stanleyycheung[@stanleyycheung]

View File

@@ -1,11 +1,6 @@
= Changelog
include::ROOT:partial$component-attributes.adoc[]
[[release-0.28.0]]
== 0.28.0 (2025-02-26)
xref:0.28.adoc[Release notes]
[[release-0.27.2]]
== 0.27.2 (2025-01-22)

View File

@@ -1,8 +1,5 @@
= Release Notes
The Pkl team aims to release a new version of Pkl in February, June, and October of each year.
* xref:0.28.adoc[0.28 Release Notes]
* xref:0.27.adoc[0.27 Release Notes]
* xref:0.26.adoc[0.26 Release Notes]
* xref:0.25.adoc[0.25 Release Notes]

View File

@@ -12,7 +12,7 @@ XXX
The next release (XXX) is scheduled for XXX (e.g., August 2, 2021).
Please send feedback and questions to https://github.com/apple/pkl/discussions[GitHub Discussions], or submit an issue on https://github.com/apple/pkl/issues/new[GitHub]. +
Please send feedback and questions to https://github.com/apple/pkl/discussions[GitHub Discussions], or submit an issue on https://github.com/apple/pkl/issues/new[Github]. +
[small]#Pkl is hosted on https://github.com/apple/pkl[GitHub].
To get started, follow xref:pkl-cli:index.adoc#installation[Installation].#

View File

@@ -356,7 +356,7 @@ myString = #"foo \ bar \ baz"#
myString = "foo \\ bar \\ baz"
----
NOTE: Sometimes, using custom string delimiters makes source code harder to read. For example, the `+\#+` literal reads better using escapes (`"\\#"`) than using custom string delimiters (`+##"\#"##+`).
NOTE: Sometimes, using custom string delimiters makes source code harder to read. For example, the `+\#+` literal reads better using escapes (`"\\#"`) than using custom string delimimters (`+##"\#"##+`).
=== Interpolation

View File

@@ -38,10 +38,7 @@
* xref:ROOT:examples.adoc[Examples]
* xref:ROOT:evolution-and-roadmap.adoc[Evolution and Roadmap]
* xref:release-notes:index.adoc[Release Notes]
** xref:release-notes:0.28.adoc[0.28 Release Notes]
** xref:release-notes:0.27.adoc[0.27 Release Notes]
** xref:release-notes:0.26.adoc[0.26 Release Notes]
** xref:release-notes:0.25.adoc[0.25 Release Notes]

View File

@@ -16,14 +16,15 @@ import org.pkl.core.Loggers
import org.pkl.core.SecurityManagers
import org.pkl.core.StackFrameTransformers
import org.pkl.core.module.ModuleKeyFactories
import org.pkl.core.parser.LexParseException
import org.pkl.core.parser.Parser
import org.pkl.core.parser.antlr.PklParser
import org.pkl.core.repl.ReplRequest
import org.pkl.core.repl.ReplResponse
import org.pkl.core.repl.ReplServer
import org.pkl.core.util.IoUtils
import org.antlr.v4.runtime.ParserRuleContext
import org.pkl.core.http.HttpClient
import org.pkl.core.parser.Parser
import org.pkl.core.parser.ParserError
import org.pkl.core.parser.syntax.ClassProperty
import org.pkl.core.resource.ResourceReaders
import java.nio.file.Files
import kotlin.io.path.isDirectory
@@ -37,7 +38,7 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
private val projectDir = rootProjectDir.resolve("docs")
private val docsDir = projectDir.resolve("modules")
private companion object {
companion object {
val headingRegex = Regex("""(?u)^\s*(=++)\s*(.+)""")
val collapsibleBlockRegex = Regex("""(?u)^\s*\[%collapsible""")
val codeBlockRegex = Regex("""(?u)^\s*\[source(?:%(tested|parsed)(%error)?)?(?:,\{?([a-zA-Z-_]+)}?)?""")
@@ -149,7 +150,6 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
}
}
@Suppress("DEPRECATION")
private fun parseAsciidoc(docDescriptor: Descriptor.Path, selectors: List<UniqueIdSelector>) {
var line = ""
var prevLine = ""
@@ -302,7 +302,7 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
override fun getType() = Type.TEST
private val parsed: org.pkl.core.parser.syntax.Node by lazy {
private val parsed: ParserRuleContext by lazy {
when (language) {
"pkl" -> Parser().parseModule(code)
"pkl-expr" -> Parser().parseExpressionInput(code)
@@ -317,7 +317,7 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
if (expectError) {
throw AssertionError("Expected a parse error, but got none.")
}
} catch (e: ParserError) {
} catch (e: LexParseException) {
if (!expectError) {
throw AssertionError(e.message)
}
@@ -334,7 +334,7 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
)
)
val properties = parsed.children()?.filterIsInstance<ClassProperty>() ?: emptyList()
val properties = parsed.children.filterIsInstance<PklParser.ClassPropertyContext>()
val responses = mutableListOf<ReplResponse>()
@@ -343,7 +343,7 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
responses.addAll(context.replServer.handleRequest(
ReplRequest.Eval(
"snippet",
prop.name.value,
prop.Identifier().text,
false,
true
)

View File

@@ -1,11 +1,10 @@
# suppress inspection "UnusedProperty" for whole file
group=org.pkl-lang
version=0.28.0
version=0.27.2
# google-java-format requires jdk.compiler exports
org.gradle.jvmargs= \
-XX:+UseParallelGC \
-Dfile.encoding=UTF-8 \
--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
@@ -16,5 +15,4 @@ org.gradle.jvmargs= \
org.gradle.parallel=true
org.gradle.caching=true
kotlin.stdlib.default.dependency=false
kotlin.daemon.jvmargs=-XX:+UseParallelGC
#org.gradle.workers.max=1

View File

@@ -1,24 +1,24 @@
[versions] # ordered alphabetically
antlr = "4.+"
assertj = "3.+"
assertj = "3.+"
checksumPlugin = "1.4.0"
clikt = "5.+"
clikt = "3.+"
commonMark = "0.+"
downloadTaskPlugin = "5.6.0"
geantyref = "1.+"
googleJavaFormat = "1.25.2"
googleJavaFormat = "1.21.0"
# must not use `+` because used in download URL
# 23.1.x requires JDK 20+
graalVm = "24.1.2"
graalVmJdkVersion = "21.0.5"
graalVm = "23.0.6"
graalVmJdkVersion = "17.0.12"
# slightly hacky but convenient place so we remember to update the checksum
graalVmSha256-macos-x64 = "2d9b09e28bc1bb6ff219bf62eacc4626c7740b4f1829ede9ea4450f33e9c0826"
graalVmSha256-macos-aarch64 = "cb68cb2c796f42f37a56fcd1385d8b86cca12e0b46c5618a5ed3ec7dd2260f6f"
graalVmSha256-linux-x64 = "c1960d4f9d278458bde1cd15115ac2f0b3240cb427d51cfeceb79dab91a7f5c9"
graalVmSha256-linux-aarch64 = "3ad68fbb2d13da528dfa0aea9e9345383245ec9c31094dce3905cefba9aac01e"
graalVmSha256-windows-x64 = "d5784cbdc87f84b5cbd6c9d09c6f1d4611954f139fcfc795005c58dffd7f6b41"
graalVmSha256-macos-x64 = "3ecac1471f3fa95a56c5b75c65db9e60ac4551f56eda09eb9da95e6049ea77d7"
graalVmSha256-macos-aarch64 = "4cdfdc6c9395f6773efcd191b6605f1b7c8e1b78ab900ab5cff34720a3feffc5"
graalVmSha256-linux-x64 = "b6f3dace24cf1960ec790216f4c86f00d4f43df64e4e8b548f6382f04894713f"
graalVmSha256-linux-aarch64 = "bd991d486b92deb74337b881e0f13a764c9c1e90fc358819080f7321fa5175e8"
graalVmSha256-windows-x64 = "8b978e56dddc0edc60db99794b56975740d9c52293b31549cfc3f7516fc18b43"
ideaExtPlugin = "1.1.9"
javaPoet = "0.+"
javaPoet = "1.+"
javaxInject = "1"
jansi = "2.+"
jimfs = "1.+"
@@ -29,12 +29,14 @@ jmh = "1.+"
jmhPlugin = "0.7.2"
jsr305 = "3.+"
junit = "5.+"
kotlin = "2.0.21"
kotlin = "1.7.10"
# 1.7+ generates much more verbose code
kotlinPoet = "1.6.+"
kotlinxHtml = "0.11.0"
kotlinxSerialization = "1.8.0"
ktfmt = "0.53"
# freeze until updating Kotlin version
kotlinxHtml = "0.8.1"
# freeze until updating Kotlin version
kotlinxSerialization = "1.5.1"
ktfmt = "0.44"
# replaces nuValidator's log4j dependency
# something related to log4j-1.2-api is apparently broken in 2.17.2
log4j = "2.17.1"
@@ -44,7 +46,9 @@ nuValidator = "20.+"
paguro = "3.+"
shadowPlugin = "8.1.1"
slf4j = "1.+"
snakeYaml = "2.+"
# snakeYaml 2.6 removed DumpSettingsBuilder::setScalarResolver,
# which is used by the external YAML renderer (org.pkl.core.YamlRenderer)
snakeYaml = "2.5"
spotlessPlugin = "6.25.0"
wiremock = "3.+"
@@ -53,7 +57,6 @@ antlr = { group = "com.tunnelvisionlabs", name = "antlr4", version.ref = "antlr"
antlrRuntime = { group = "com.tunnelvisionlabs", name = "antlr4-runtime", version.ref = "antlr" }
assertj = { group = "org.assertj", name = "assertj-core", version.ref = "assertj" }
clikt = { group = "com.github.ajalt.clikt", name = "clikt", version.ref = "clikt" }
cliktMarkdown = { group = "com.github.ajalt.clikt", name = "clikt-markdown", version.ref = "clikt" }
commonMark = { group = "org.commonmark", name = "commonmark", version.ref = "commonMark" }
commonMarkTables = { group = "org.commonmark", name = "commonmark-ext-gfm-tables", version.ref = "commonMark" }
downloadTaskPlugin = { group = "de.undercouch", name = "gradle-download-task", version.ref = "downloadTaskPlugin" }
@@ -61,7 +64,7 @@ geantyref = { group = "io.leangen.geantyref", name = "geantyref", version.ref =
graalCompiler = { group = "org.graalvm.compiler", name = "compiler", version.ref = "graalVm" }
graalSdk = { group = "org.graalvm.sdk", name = "graal-sdk", version.ref = "graalVm" }
graalJs = { group = "org.graalvm.js", name = "js", version.ref = "graalVm" }
javaPoet = { group = "com.palantir.javapoet", name = "javapoet", version.ref = "javaPoet" }
javaPoet = { group = "com.squareup", name = "javapoet", version.ref = "javaPoet" }
javaxInject = { group = "javax.inject", name = "javax.inject", version.ref = "javaxInject" }
jansi = { group = "org.fusesource.jansi", name = "jansi", version.ref = "jansi" }
jimfs = { group = "com.google.jimfs", name = "jimfs", version.ref = "jimfs" }
@@ -76,7 +79,8 @@ kotlinCompilerEmbeddable = { group = "org.jetbrains.kotlin", name = "kotlin-comp
kotlinPlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
kotlinPoet = { group = "com.squareup", name = "kotlinpoet", version.ref = "kotlinPoet" }
kotlinReflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" }
kotlinScripting = { group = "org.jetbrains.kotlin", name = "kotlin-scripting-jsr223", version.ref = "kotlin" }
kotlinScriptingCompilerEmbeddable = { group = "org.jetbrains.kotlin", name = "kotlin-scripting-compiler-embeddable", version.ref = "kotlin" }
kotlinScriptUtil = { group = "org.jetbrains.kotlin", name = "kotlin-script-util", version.ref = "kotlin" }
kotlinStdLib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" }
kotlinxHtml = { group = "org.jetbrains.kotlinx", name = "kotlinx-html-jvm", version.ref = "kotlinxHtml" }
kotlinxSerializationJson = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerialization" }
@@ -94,8 +98,6 @@ spotlessPlugin = { group = "com.diffplug.spotless", name = "spotless-plugin-grad
svm = { group = "org.graalvm.nativeimage", name = "svm", version.ref = "graalVm" }
truffleApi = { group = "org.graalvm.truffle", name = "truffle-api", version.ref = "graalVm" }
truffleDslProcessor = { group = "org.graalvm.truffle", name = "truffle-dsl-processor", version.ref = "graalVm" }
truffleSvm = { group = "org.graalvm.nativeimage", name = "truffle-runtime-svm", version.ref = "graalVm" }
truffleRuntime = { group = "org.graalvm.truffle", name = "truffle-runtime", version.ref = "graalVm" }
wiremock = { group = "org.wiremock", name = "wiremock", version.ref = "wiremock" }
[plugins] # ordered alphabetically

View File

@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=8d97a97984f6cbd2b85fe4c60a743440a347544bf18818048e611f5288d46c94
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
distributionSha256Sum=31c55713e40233a8303827ceb42ca48a47267a0ad4bab9177123121e71524c26
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

3
gradlew vendored
View File

@@ -86,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum

View File

@@ -2,15 +2,15 @@
"catalogs": {},
"aliases": {
"pkl": {
"script-ref": "org.pkl-lang:pkl-cli-java:0.28.0",
"script-ref": "org.pkl-lang:pkl-cli-java:0.27.2",
"java-agents": []
},
"pkl-codegen-java": {
"script-ref": "org.pkl-lang:pkl-codegen-java:0.28.0",
"script-ref": "org.pkl-lang:pkl-codegen-java:0.27.2",
"java-agents": []
},
"pkl-codegen-kotlin": {
"script-ref": "org.pkl-lang:pkl-codegen-kotlin:0.28.0",
"script-ref": "org.pkl-lang:pkl-codegen-kotlin:0.27.2",
"java-agents": []
}
},

30
pkl-certs/gradle.lockfile Normal file
View File

@@ -0,0 +1,30 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
net.bytebuddy:byte-buddy:1.14.16=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.7.10=kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-reflect:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-script-runtime:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-scripting-common:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-jvm:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains:annotations:13.0=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.10.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-engine:5.10.2=testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-params:5.10.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.10.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.platform:junit-platform-engine:1.10.2=testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit:junit-bom:5.10.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
empty=annotationProcessor,apiDependenciesMetadata,compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtimeClasspath,runtimeOnlyDependenciesMetadata,signatures,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions

View File

@@ -1,55 +1,38 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
com.ethlo.time:itu:1.10.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-annotations:2.18.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-core:2.18.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-databind:2.18.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.18.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.ajalt.clikt:clikt-core-jvm:5.0.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ajalt.clikt:clikt-core:5.0.3=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.ajalt.clikt:clikt-jvm:5.0.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ajalt.clikt:clikt-markdown-jvm:5.0.3=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.clikt:clikt-markdown:5.0.3=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.clikt:clikt:5.0.3=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.ajalt.colormath:colormath-jvm:3.6.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ajalt.colormath:colormath:3.6.0=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.ajalt.mordant:mordant-core-jvm:3.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-core:3.0.1=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm-ffm-jvm:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm-ffm:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm-graal-ffi-jvm:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm-graal-ffi:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm-jna-jvm:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm-jna:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm:3.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-markdown-jvm:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-markdown:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant:3.0.1=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.ethlo.time:itu:1.10.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-annotations:2.17.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-core:2.17.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-databind:2.17.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.17.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.ajalt.clikt:clikt-jvm:3.5.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ajalt.clikt:clikt:3.5.4=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.jknack:handlebars-helpers:4.3.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.jknack:handlebars:4.3.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.google.errorprone:error_prone_annotations:2.36.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.google.errorprone:error_prone_annotations:2.28.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.google.guava:failureaccess:1.0.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.google.guava:guava:33.4.0-jre=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.google.guava:guava:33.3.1-jre=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.google.j2objc:j2objc-annotations:3.0.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.jayway.jsonpath:json-path:2.9.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.networknt:json-schema-validator:1.5.5=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.networknt:json-schema-validator:1.5.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.tunnelvisionlabs:antlr4-runtime:4.9.0=runtimeClasspath,testRuntimeClasspath
commons-fileupload:commons-fileupload:1.5=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
commons-io:commons-io:2.11.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
net.java.dev.jna:jna:5.14.0=runtimeClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.14.18=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
net.javacrumbs.json-unit:json-unit-core:2.40.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
net.minidev:accessors-smart:2.5.1=testRuntimeClasspath
net.minidev:json-smart:2.5.1=testRuntimeClasspath
net.sf.jopt-simple:jopt-simple:5.0.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.apache.httpcomponents.client5:httpclient5:5.4.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.apache.httpcomponents.core5:httpcore5-h2:5.3.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.apache.httpcomponents.core5:httpcore5:5.3.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.27.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.apache.httpcomponents.client5:httpclient5:5.3.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.apache.httpcomponents.core5:httpcore5-h2:5.2.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.apache.httpcomponents.core5:httpcore5:5.2.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.checkerframework:checker-qual:3.43.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.eclipse.jetty.http2:http2-common:11.0.24=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.eclipse.jetty.http2:http2-hpack:11.0.24=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
@@ -72,73 +55,48 @@ org.eclipse.jetty:jetty-util:11.0.24=testCompileClasspath,testImplementationDepe
org.eclipse.jetty:jetty-webapp:11.0.24=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.eclipse.jetty:jetty-xml:11.0.24=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.compiler:compiler:24.1.2=compileClasspath,compileOnlyDependenciesMetadata
org.graalvm.nativeimage:native-image-base:24.1.2=compileClasspath,compileOnlyDependenciesMetadata
org.graalvm.nativeimage:objectfile:24.1.2=compileClasspath,compileOnlyDependenciesMetadata
org.graalvm.nativeimage:pointsto:24.1.2=compileClasspath,compileOnlyDependenciesMetadata
org.graalvm.nativeimage:svm:24.1.2=compileClasspath,compileOnlyDependenciesMetadata
org.graalvm.nativeimage:truffle-runtime-svm:24.1.2=compileClasspath,compileOnlyDependenciesMetadata
org.graalvm.polyglot:polyglot:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:collections:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,runtimeClasspath,testRuntimeClasspath
org.graalvm.sdk:jniutils:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:nativeimage:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:word:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.truffle:truffle-api:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.truffle:truffle-compiler:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.truffle:truffle-runtime:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.compiler:compiler:23.0.6=compileClasspath,compileOnlyDependenciesMetadata
org.graalvm.nativeimage:native-image-base:23.0.6=compileClasspath,compileOnlyDependenciesMetadata
org.graalvm.nativeimage:objectfile:23.0.6=compileClasspath,compileOnlyDependenciesMetadata
org.graalvm.nativeimage:pointsto:23.0.6=compileClasspath,compileOnlyDependenciesMetadata
org.graalvm.nativeimage:svm:23.0.6=compileClasspath,compileOnlyDependenciesMetadata
org.graalvm.sdk:graal-sdk:23.0.6=compileClasspath,compileOnlyDependenciesMetadata,runtimeClasspath,testRuntimeClasspath
org.graalvm.truffle:truffle-api:23.0.6=compileClasspath,compileOnlyDependenciesMetadata,runtimeClasspath,testRuntimeClasspath
org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.hamcrest:hamcrest:2.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-build-tools-impl:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-compiler-runner:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-daemon-client:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:2.0.21=kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-native-prebuilt:2.0.21=kotlinNativeBundleConfiguration
org.jetbrains.kotlin:kotlin-reflect:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-script-runtime:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-scripting-common:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17
org.jetbrains.kotlin:kotlin-scripting-jvm:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17
org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.0.21=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.0.21=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:2.0.21=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains:annotations:13.0=compileClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains:markdown-jvm:0.7.3=runtimeClasspath,testRuntimeClasspath
org.jetbrains:markdown:0.7.3=runtimeClasspath,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.7.10=kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-reflect:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-script-runtime:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-scripting-common:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-jvm:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:1.7.10=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains:annotations:13.0=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jline:jline-native:3.23.0=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jline:jline-reader:3.23.0=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jline:jline-terminal-jansi:3.23.0=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jline:jline-terminal:3.23.0=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-api:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-engine:5.8.2=testJdk17RuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.jupiter:junit-jupiter:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.platform:junit-platform-commons:1.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.platform:junit-platform-commons:1.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.platform:junit-platform-engine:1.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.platform:junit-platform-engine:1.8.2=testJdk17RuntimeClasspath
org.junit.platform:junit-platform-launcher:1.8.2=testJdk17RuntimeClasspath
org.junit:junit-bom:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit:junit-bom:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-engine:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-params:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.platform:junit-platform-engine:1.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit:junit-bom:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.msgpack:msgpack-core:0.9.8=runtimeClasspath,testRuntimeClasspath
org.opentest4j:opentest4j:1.2.0=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.organicdesign:Paguro:3.10.3=runtimeClasspath,testRuntimeClasspath
org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.snakeyaml:snakeyaml-engine:2.9=runtimeClasspath,testRuntimeClasspath
org.wiremock:wiremock:3.11.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.slf4j:slf4j-api:2.0.13=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.snakeyaml:snakeyaml-engine:2.5=runtimeClasspath,testRuntimeClasspath
org.wiremock:wiremock:3.9.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.xmlunit:xmlunit-core:2.10.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.xmlunit:xmlunit-legacy:2.10.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.xmlunit:xmlunit-placeholders:2.10.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.yaml:snakeyaml:2.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
empty=annotationProcessor,archives,compile,intransitiveDependenciesMetadata,javaExecutable,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtime,runtimeOnlyDependenciesMetadata,shadow,signatures,sourcesJar,stagedAlpineLinuxAmd64Executable,stagedLinuxAarch64Executable,stagedLinuxAmd64Executable,stagedMacAarch64Executable,stagedMacAmd64Executable,stagedWindowsAmd64Executable,testAnnotationProcessor,testApiDependenciesMetadata,testCompile,testCompileOnly,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testJdk17AnnotationProcessor,testJdk17ApiDependenciesMetadata,testJdk17CompileOnlyDependenciesMetadata,testJdk17IntransitiveDependenciesMetadata,testJdk17KotlinScriptDefExtensions,testKotlinScriptDef,testKotlinScriptDefExtensions,testRuntime
org.yaml:snakeyaml:2.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
empty=annotationProcessor,archives,compile,intransitiveDependenciesMetadata,javaExecutable,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtime,runtimeOnlyDependenciesMetadata,shadow,signatures,sourcesJar,stagedAlpineLinuxAmd64Executable,stagedLinuxAarch64Executable,stagedLinuxAmd64Executable,stagedMacAarch64Executable,stagedMacAmd64Executable,stagedWindowsAmd64Executable,testAnnotationProcessor,testApiDependenciesMetadata,testCompile,testCompileOnly,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions,testRuntime

View File

@@ -13,9 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.ByteArrayOutputStream
import org.gradle.kotlin.dsl.support.serviceOf
plugins {
pklAllProjects
pklKotlinLibrary
@@ -53,9 +50,6 @@ val stagedWindowsAmd64Executable: Configuration by configurations.creating
dependencies {
compileOnly(libs.svm)
compileOnly(libs.truffleSvm)
implementation(libs.truffleRuntime)
compileOnly(libs.graalSdk)
// CliEvaluator exposes PClass
api(projects.pklCore)
@@ -68,7 +62,11 @@ dependencies {
implementation(libs.jlineTerminal)
implementation(libs.jlineTerminalJansi)
implementation(projects.pklServer)
implementation(libs.clikt)
implementation(libs.clikt) {
// force clikt to use our version of the kotlin stdlib
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8")
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-common")
}
testImplementation(projects.pklCommonsTest)
testImplementation(libs.wiremock)
@@ -84,8 +82,10 @@ dependencies {
}
tasks.jar {
manifest.attributes +=
mapOf("Main-Class" to "org.pkl.cli.Main", "Add-Exports" to buildInfo.jpmsExportsForJarManifest)
manifest { attributes += mapOf("Main-Class" to "org.pkl.cli.Main") }
// not required at runtime
exclude("org/pkl/cli/svm/**")
}
tasks.javadoc { enabled = false }
@@ -96,6 +96,9 @@ tasks.shadowJar {
exclude("META-INF/maven/**")
exclude("META-INF/upgrade/**")
// org.antlr.v4.runtime.misc.RuleDependencyProcessor
exclude("META-INF/services/javax.annotation.processing.Processor")
exclude("module-info.*")
}
@@ -123,100 +126,38 @@ val testJavaExecutable by
(configurations.testRuntimeClasspath.get() - configurations.runtimeClasspath.get())
}
// Setup `testJavaExecutable` tasks for multi-JDK testing.
val testJavaExecutableOnOtherJdks =
if (buildInfo.multiJdkTesting) {
buildInfo.multiJdkTestingWith(testJavaExecutable)
} else {
emptyList()
}
// Prepare a run of the fat JAR, optionally with a specific Java launcher.
private fun setupJavaExecutableRun(
name: String,
args: Array<String>,
launcher: Provider<JavaLauncher>? = null,
configurator: Exec.() -> Unit = {},
) =
tasks.register(name, Exec::class) {
dependsOn(javaExecutable)
val outputFile = layout.buildDirectory.file(name) // dummy output to satisfy up-to-date check
outputs.file(outputFile)
executable =
when (launcher) {
null -> "java"
else -> launcher.get().executablePath.asFile.absolutePath
}
args("-jar", javaExecutable.get().outputs.files.singleFile.toString(), *args)
doFirst { outputFile.get().asFile.delete() }
doLast { outputFile.get().asFile.writeText("OK") }
configurator()
}
tasks.check { dependsOn(testJavaExecutable) }
// 0.14 Java executable was broken because javaExecutable.jvmArgs wasn't commented out.
// To catch this and similar problems, test that Java executable starts successfully.
val testStartJavaExecutable by
setupJavaExecutableRun("testStartJavaExecutable", arrayOf("--version"))
tasks.registering(Exec::class) {
dependsOn(javaExecutable)
val outputFile =
layout.buildDirectory.file(
"testStartJavaExecutable"
) // dummy output to satisfy up-to-date check
outputs.file(outputFile)
// Setup `testStartJavaExecutable` tasks for multi-JDK testing.
val testStartJavaExecutableOnOtherJdks =
if (buildInfo.multiJdkTesting) {
buildInfo.jdkTestRange.map { jdkTarget ->
setupJavaExecutableRun(
"testStartJavaExecutableJdk${jdkTarget.asInt()}",
arrayOf("--version"),
serviceOf<JavaToolchainService>().launcherFor { languageVersion = jdkTarget },
)
if (buildInfo.os.isWindows) {
executable = "java"
args("-jar", javaExecutable.get().outputs.files.singleFile.toString(), "--version")
} else {
executable = javaExecutable.get().outputs.files.singleFile.toString()
args("--version")
}
} else {
emptyList()
doFirst { outputFile.get().asFile.delete() }
doLast { outputFile.get().asFile.writeText("OK") }
}
val evalTestFlags = arrayOf("eval", "-x", "1 + 1", "pkl:base")
fun Exec.useRootDirAndSuppressOutput() {
workingDir = rootProject.layout.projectDirectory.asFile
standardOutput = ByteArrayOutputStream() // we only care that this exec doesn't fail
}
// 0.28 Preparing for JDK21 toolchains revealed that `testStartJavaExecutable` may pass, even though
// the evaluator fails. To catch this, we need to test the evaluator. We render the CircleCI config
// as a realistic test of the fat JAR.
val testEvalJavaExecutable by
setupJavaExecutableRun("testEvalJavaExecutable", evalTestFlags) { useRootDirAndSuppressOutput() }
// Run the same evaluator tests on all configured JDK test versions.
val testEvalJavaExecutableOnOtherJdks =
buildInfo.jdkTestRange.map { jdkTarget ->
setupJavaExecutableRun(
"testEvalJavaExecutableJdk${jdkTarget.asInt()}",
evalTestFlags,
serviceOf<JavaToolchainService>().launcherFor { languageVersion = jdkTarget },
) {
useRootDirAndSuppressOutput()
}
}
tasks.check {
dependsOn(
testJavaExecutable,
testStartJavaExecutable,
testJavaExecutableOnOtherJdks,
testStartJavaExecutableOnOtherJdks,
testEvalJavaExecutable,
testEvalJavaExecutableOnOtherJdks,
)
}
tasks.check { dependsOn(testStartJavaExecutable) }
fun Exec.configureExecutable(
graalVm: BuildInfo.GraalVm,
outputFile: Provider<RegularFile>,
extraArgs: List<String> = listOf(),
extraArgs: List<String> = listOf()
) {
inputs
.files(sourceSets.main.map { it.output })
@@ -238,13 +179,11 @@ fun Exec.configureExecutable(
executable = "${graalVm.baseDir}/bin/$nativeImageCommandName"
// JARs to exclude from the class path for the native-image build.
val exclusions = listOf(libs.graalSdk).map { it.get().module.name }
val exclusions = listOf(libs.truffleApi, libs.graalSdk).map { it.get().module.name }
// https://www.graalvm.org/22.0/reference-manual/native-image/Options/
argumentProviders.add(
CommandLineArgumentProvider {
buildList {
// must be emitted before any experimental options are used
add("-H:+UnlockExperimentalVMOptions")
// currently gives a deprecation warning, but we've been told
// that the "initialize everything at build time" *CLI* option is likely here to stay
add("--initialize-at-build-time=")
@@ -255,9 +194,9 @@ fun Exec.configureExecutable(
add("-H:IncludeResources=org/jline/utils/.*")
add("-H:IncludeResourceBundles=org.pkl.core.errorMessages")
add("-H:IncludeResources=org/pkl/commons/cli/PklCARoots.pem")
add("--macro:truffle")
add("-H:Class=org.pkl.cli.Main")
add("-o")
add(outputFile.get().asFile.name)
add("-H:Name=${outputFile.get().asFile.name}")
// the actual limit (currently) used by native-image is this number + 1400 (idea is to
// compensate for Truffle's own nodes)
add("-H:MaxRuntimeCompileMethods=1800")
@@ -272,11 +211,7 @@ fun Exec.configureExecutable(
if (!buildInfo.isReleaseBuild) {
add("-Ob")
}
if (buildInfo.isNativeArch) {
add("-march=native")
} else {
add("-march=compatibility")
}
add("-march=compatibility")
// native-image rejects non-existing class path entries -> filter
add("--class-path")
val pathInput =
@@ -305,7 +240,7 @@ val macExecutableAmd64: TaskProvider<Exec> by
dependsOn(":installGraalVmAmd64")
configureExecutable(
buildInfo.graalVmAmd64,
layout.buildDirectory.file("executable/pkl-macos-amd64"),
layout.buildDirectory.file("executable/pkl-macos-amd64")
)
}
@@ -316,7 +251,7 @@ val macExecutableAarch64: TaskProvider<Exec> by
configureExecutable(
buildInfo.graalVmAarch64,
layout.buildDirectory.file("executable/pkl-macos-aarch64"),
listOf("-H:+AllowDeprecatedBuilderClassesOnImageClasspath"),
listOf("-H:+AllowDeprecatedBuilderClassesOnImageClasspath")
)
}
@@ -326,7 +261,7 @@ val linuxExecutableAmd64: TaskProvider<Exec> by
dependsOn(":installGraalVmAmd64")
configureExecutable(
buildInfo.graalVmAmd64,
layout.buildDirectory.file("executable/pkl-linux-amd64"),
layout.buildDirectory.file("executable/pkl-linux-amd64")
)
}
@@ -346,7 +281,7 @@ val linuxExecutableAarch64: TaskProvider<Exec> by
// Ensure compatibility for kernels with page size set to 4k, 16k and 64k
// (e.g. Raspberry Pi 5, Asahi Linux)
"-H:PageSize=65536"
),
)
)
}
@@ -362,7 +297,7 @@ val alpineExecutableAmd64: TaskProvider<Exec> by
configureExecutable(
buildInfo.graalVmAmd64,
layout.buildDirectory.file("executable/pkl-alpine-linux-amd64"),
listOf("--static", "--libc=musl"),
listOf("--static", "--libc=musl")
)
}
@@ -372,7 +307,7 @@ val windowsExecutableAmd64: TaskProvider<Exec> by
configureExecutable(
buildInfo.graalVmAmd64,
layout.buildDirectory.file("executable/pkl-windows-amd64"),
listOf("-Dfile.encoding=UTF-8"),
listOf("-Dfile.encoding=UTF-8")
)
}
@@ -428,7 +363,7 @@ publishing {
description.set(
"""
Pkl CLI executable for Java.
Can be executed directly, or with `java -jar <path/to/jpkl>`.
Can be executed directly on *nix (if the `java` command is found on the PATH) and with `java -jar` otherwise.
Requires Java 17 or higher.
"""
.trimIndent()

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,15 +21,15 @@ import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.truffle.TruffleFeature;
import java.util.Map;
import org.pkl.core.ast.builder.AstBuilder;
/**
* Workaround to prevent the native-image build error "Detected a started Thread in the image
* heap.". The cause of this error is the use of {@link org.graalvm.polyglot.Context} in the
* (intentionally) statically reachable class {@link org.pkl.core.runtime.StdLibModule}.
*
* <p>A cleaner solution would be to have a separate {@link AstBuilder} for stdlib modules that
* produces a fully initialized module object without executing any Truffle nodes.
* <p>A cleaner solution would be to have a separate {@link org.pkl.core.ast.builder.AstBuilder} for
* stdlib modules that produces a fully initialized module object without executing any Truffle
* nodes.
*
* <p>This class is automatically discovered by native-image; no registration is required.
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,11 +21,11 @@ import java.io.Writer
import java.net.URI
import java.nio.file.Path
import java.nio.file.StandardOpenOption
import kotlin.io.path.createParentDirectories
import kotlin.io.path.exists
import kotlin.io.path.isDirectory
import org.pkl.commons.cli.CliCommand
import org.pkl.commons.cli.CliException
import org.pkl.commons.createParentDirectories
import org.pkl.commons.currentWorkingDir
import org.pkl.commons.writeString
import org.pkl.core.Closeables
@@ -165,13 +165,13 @@ constructor(
options.moduleOutputSeparator + '\n',
Charsets.UTF_8,
StandardOpenOption.WRITE,
StandardOpenOption.APPEND,
StandardOpenOption.APPEND
)
outputFile.writeString(
output,
Charsets.UTF_8,
StandardOpenOption.WRITE,
StandardOpenOption.APPEND,
StandardOpenOption.APPEND
)
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -80,6 +80,6 @@ data class CliEvaluatorOptions(
) {
companion object {
val defaults: CliEvaluatorOptions = CliEvaluatorOptions(CliBaseOptions())
val defaults = CliEvaluatorOptions(CliBaseOptions())
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,8 @@
package org.pkl.cli
import java.io.Writer
import kotlin.io.path.createParentDirectories
import org.pkl.commons.cli.CliCommand
import org.pkl.commons.createParentDirectories
import org.pkl.commons.writeString
import org.pkl.core.Closeables
import org.pkl.core.ModuleSource
@@ -26,7 +26,7 @@ class CliImportAnalyzer
@JvmOverloads
constructor(
private val options: CliImportAnalyzerOptions,
private val consoleWriter: Writer = System.out.writer(),
private val consoleWriter: Writer = System.out.writer()
) : CliCommand(options.base) {
override fun doRun() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@ import org.pkl.core.packages.PackageUri
class CliPackageDownloader(
baseOptions: CliBaseOptions,
private val packageUris: List<PackageUri>,
private val noTransitive: Boolean,
private val noTransitive: Boolean
) : CliCommand(baseOptions) {
override fun doRun() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,11 +32,11 @@ class CliProjectPackager(
private val outputPath: String,
private val skipPublishCheck: Boolean,
private val consoleWriter: Writer = System.out.writer(),
private val errWriter: Writer = System.err.writer(),
private val errWriter: Writer = System.err.writer()
) : CliProjectCommand(baseOptions, projectDirs) {
private fun runApiTests(project: Project) {
val apiTests = project.`package`!!.apiTests()
val apiTests = project.`package`!!.apiTests
if (apiTests.isEmpty()) return
val normalizeApiTests = apiTests.map { project.projectDir.resolve(it).toUri() }
val testRunner =
@@ -49,7 +49,7 @@ class CliProjectPackager(
try {
testRunner.run()
} catch (e: CliTestException) {
throw CliException(ErrorMessages.create("packageTestsFailed", project.`package`!!.uri()))
throw CliException(ErrorMessages.create("packageTestsFailed", project.`package`!!.uri))
}
}
@@ -67,8 +67,8 @@ class CliProjectPackager(
}
// Require that all local projects are included
projects.forEach { proj ->
proj.dependencies.localDependencies().values.forEach { localDep ->
val projectDir = Path.of(localDep.projectFileUri()).parent
proj.dependencies.localDependencies.values.forEach { localDep ->
val projectDir = Path.of(localDep.projectFileUri).parent
if (projects.none { it.projectDir == projectDir }) {
throw CliException(
ErrorMessages.create("missingProjectInPackageCommand", proj.projectDir, projectDir)
@@ -85,7 +85,7 @@ class CliProjectPackager(
securityManager,
httpClient,
skipPublishCheck,
consoleWriter,
consoleWriter
)
.createPackages()
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@ class CliProjectResolver(
baseOptions: CliBaseOptions,
projectDirs: List<Path>,
private val consoleWriter: Writer = System.out.writer(),
private val errWriter: Writer = System.err.writer(),
private val errWriter: Writer = System.err.writer()
) : CliProjectCommand(baseOptions, projectDirs) {
override fun doRun() {
for (projectFile in normalizedProjectFiles) {
@@ -38,10 +38,10 @@ class CliProjectResolver(
allowedModules,
allowedResources,
SecurityManagers.defaultTrustLevels,
rootDir,
rootDir
),
httpClient,
moduleCacheDir,
moduleCacheDir
)
val dependencies = ProjectDependenciesResolver(project, packageResolver, errWriter).resolve()
val depsFile =

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,13 +34,13 @@ internal class CliRepl(private val options: CliEvaluatorOptions) : CliCommand(op
allowedModules,
allowedResources,
SecurityManagers.defaultTrustLevels,
rootDir,
rootDir
),
httpClient,
Loggers.stdErr(),
listOf(
ModuleKeyFactories.standardLibrary,
ModuleKeyFactories.modulePath(modulePathResolver),
ModuleKeyFactories.modulePath(modulePathResolver)
) +
ModuleKeyFactories.fromServiceProviders() +
listOf(
@@ -48,7 +48,7 @@ internal class CliRepl(private val options: CliEvaluatorOptions) : CliCommand(op
ModuleKeyFactories.http,
ModuleKeyFactories.pkg,
ModuleKeyFactories.projectpackage,
ModuleKeyFactories.genericUrl,
ModuleKeyFactories.genericUrl
),
listOf(
ResourceReaders.environmentVariable(),
@@ -58,7 +58,7 @@ internal class CliRepl(private val options: CliEvaluatorOptions) : CliCommand(op
ResourceReaders.http(),
ResourceReaders.https(),
ResourceReaders.pkg(),
ResourceReaders.projectpackage(),
ResourceReaders.projectpackage()
),
environmentVariables,
externalProperties,

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@ import org.pkl.core.messaging.ProtocolException
import org.pkl.server.Server
class CliServer(options: CliBaseOptions) : CliCommand(options) {
override fun doRun(): Unit =
override fun doRun() =
try {
val server = Server.stream(System.`in`, System.out)
server.use { it.start() }

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@ constructor(
private val options: CliBaseOptions,
private val testOptions: CliTestOptions,
private val consoleWriter: Writer = System.out.writer(),
private val errWriter: Writer = System.err.writer(),
private val errWriter: Writer = System.err.writer()
) : CliCommand(options) {
override fun doRun() {
@@ -51,9 +51,9 @@ constructor(
// keep in sync with error message thrown by clikt
throw CliException(
"""
Usage: pkl test [<options>] <modules>...
Usage: pkl test [OPTIONS] <modules>...
Error: missing argument <modules>
Error: Missing argument "<modules>"
"""
.trimIndent()
)

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,11 +17,26 @@
package org.pkl.cli
import com.github.ajalt.clikt.core.main
import com.github.ajalt.clikt.core.subcommands
import org.pkl.cli.commands.*
import org.pkl.commons.cli.cliMain
import org.pkl.core.Release
/** Main method of the Pkl CLI (command-line evaluator and REPL). */
internal fun main(args: Array<String>) {
cliMain { RootCommand().main(args) }
cliMain {
val version = Release.current().versionInfo()
val helpLink = "${Release.current().documentation().homepage()}pkl-cli/index.html#usage"
RootCommand("pkl", version, helpLink)
.subcommands(
EvalCommand(helpLink),
ReplCommand(helpLink),
ServerCommand(helpLink),
TestCommand(helpLink),
ProjectCommand(helpLink),
DownloadPackageCommand(helpLink),
AnalyzeCommand(helpLink),
)
.main(args)
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
*/
package org.pkl.cli.commands
import com.github.ajalt.clikt.core.Context
import com.github.ajalt.clikt.core.NoOpCliktCommand
import com.github.ajalt.clikt.core.subcommands
import com.github.ajalt.clikt.parameters.options.option
@@ -26,35 +25,42 @@ import org.pkl.cli.CliImportAnalyzerOptions
import org.pkl.commons.cli.commands.ModulesCommand
import org.pkl.commons.cli.commands.single
class AnalyzeCommand : NoOpCliktCommand(name = "analyze") {
override fun help(context: Context) = "Commands related to static analysis"
override fun helpEpilog(context: Context) = "For more information, visit $helpLink"
class AnalyzeCommand(helpLink: String) :
NoOpCliktCommand(
name = "analyze",
help = "Commands related to static analysis",
epilog = "For more information, visit $helpLink"
) {
init {
subcommands(AnalyzeImportsCommand())
}
}
class AnalyzeImportsCommand : ModulesCommand(name = "imports", helpLink = helpLink) {
override val helpString = "Prints the graph of modules imported by the input module(s)."
private val outputPath: Path? by
option(
names = arrayOf("-o", "--output-path"),
metavar = "path",
help = "File path where the output file is placed.",
)
.path()
.single()
override fun run() {
val options =
CliImportAnalyzerOptions(
base = baseOptions.baseOptions(modules, projectOptions),
outputFormat = baseOptions.format,
outputPath = outputPath,
)
CliImportAnalyzer(options).run()
subcommands(AnalyzeImportsCommand(helpLink))
}
companion object {
class AnalyzeImportsCommand(helpLink: String) :
ModulesCommand(
name = "imports",
helpLink = helpLink,
help = "Prints the the graph of modules imported by the input module(s)."
) {
private val outputPath: Path? by
option(
names = arrayOf("-o", "--output-path"),
metavar = "<path>",
help = "File path where the output file is placed."
)
.path()
.single()
override fun run() {
val options =
CliImportAnalyzerOptions(
base = baseOptions.baseOptions(modules, projectOptions),
outputFormat = baseOptions.format,
outputPath = outputPath
)
CliImportAnalyzer(options).run()
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,34 +27,36 @@ import org.pkl.commons.cli.commands.ProjectOptions
import org.pkl.commons.cli.commands.single
import org.pkl.core.packages.PackageUri
class DownloadPackageCommand : BaseCommand(name = "download-package", helpLink = helpLink) {
override val helpString =
"""
Download package(s)
This command downloads the specified packages to the cache directory.
If the package already exists in the cache directory, this command is a no-op.
Examples:
```
# Download two packages
$ pkl download-package package://example.com/package1@1.0.0 package://example.com/package2@1.0.0
```
class DownloadPackageCommand(helpLink: String) :
BaseCommand(
name = "download-package",
helpLink = helpLink,
help =
"""
Download package(s)
This command downloads the specified packages to the cache directory.
If the package already exists in the cache directory, this command is a no-op.
Examples:
```
# Download two packages
$ pkl download-package package://example.com/package1@1.0.0 package://example.com/package2@1.0.0
```
"""
.trimIndent()
.trimIndent()
) {
private val projectOptions by ProjectOptions()
private val packageUris: List<PackageUri> by
argument("package", "The package URIs to download")
argument("<package>", "The package URIs to download")
.convert { PackageUri(it) }
.multiple(required = true)
private val noTransitive: Boolean by
option(
names = arrayOf("--no-transitive"),
help = "Skip downloading transitive dependencies of a package",
help = "Skip downloading transitive dependencies of a package"
)
.single()
.flag()
@@ -63,7 +65,7 @@ class DownloadPackageCommand : BaseCommand(name = "download-package", helpLink =
CliPackageDownloader(
baseOptions.baseOptions(emptyList(), projectOptions),
packageUris,
noTransitive,
noTransitive
)
.run()
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,24 +24,26 @@ import org.pkl.cli.CliEvaluatorOptions
import org.pkl.commons.cli.commands.ModulesCommand
import org.pkl.commons.cli.commands.single
class EvalCommand : ModulesCommand(name = "eval", helpLink = helpLink) {
override val helpString = "Render pkl module(s)"
class EvalCommand(helpLink: String) :
ModulesCommand(
name = "eval",
help = "Render pkl module(s)",
helpLink = helpLink,
) {
private val outputPath: String? by
option(
names = arrayOf("-o", "--output-path"),
metavar = "path",
help = "File path where the output file is placed.",
metavar = "<path>",
help = "File path where the output file is placed."
)
.single()
private val moduleOutputSeparator: String by
option(
names = arrayOf("--module-output-separator"),
metavar = "string",
metavar = "<string>",
help =
"Separator to use when multiple module outputs are written to the same file. (default: ---)",
"Separator to use when multiple module outputs are written to the same file. (default: ---)"
)
.single()
.default("---")
@@ -49,16 +51,16 @@ class EvalCommand : ModulesCommand(name = "eval", helpLink = helpLink) {
private val expression: String? by
option(
names = arrayOf("-x", "--expression"),
metavar = "expression",
help = "Expression to be evaluated within the module.",
metavar = "<expression>",
help = "Expression to be evaluated within the module."
)
.single()
private val multipleFileOutputPath: String? by
option(
names = arrayOf("-m", "--multiple-file-output-path"),
metavar = "path",
help = "Directory where a module's multiple file output is placed.",
metavar = "<path>",
help = "Directory where a module's multiple file output is placed."
)
.single()
.validate {
@@ -79,7 +81,7 @@ class EvalCommand : ModulesCommand(name = "eval", helpLink = helpLink) {
outputFormat = baseOptions.format,
moduleOutputSeparator = moduleOutputSeparator,
multipleFileOutputPath = multipleFileOutputPath,
expression = expression ?: CliEvaluatorOptions.defaults.expression,
expression = expression ?: CliEvaluatorOptions.defaults.expression
)
CliEvaluator(options).run()
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
*/
package org.pkl.cli.commands
import com.github.ajalt.clikt.core.Context
import com.github.ajalt.clikt.core.NoOpCliktCommand
import com.github.ajalt.clikt.core.subcommands
import com.github.ajalt.clikt.parameters.arguments.argument
@@ -32,110 +31,119 @@ import org.pkl.commons.cli.commands.BaseCommand
import org.pkl.commons.cli.commands.TestOptions
import org.pkl.commons.cli.commands.single
private const val NEWLINE = '\u0085'
class ProjectCommand : NoOpCliktCommand(name = "project") {
override fun help(context: Context) = "Run commands related to projects"
override fun helpEpilog(context: Context) = "For more information, visit $helpLink"
class ProjectCommand(helpLink: String) :
NoOpCliktCommand(
name = "project",
help = "Run commands related to projects",
epilog = "For more information, visit $helpLink"
) {
init {
subcommands(ResolveCommand(), PackageCommand())
}
}
class ResolveCommand : BaseCommand(name = "resolve", helpLink = helpLink) {
override val helpString =
"""
Resolve dependencies for project(s)
This command takes the `dependencies` of `PklProject`s, and writes the
resolved versions to `PklProject.deps.json` files.
Examples:
```
# Search the current working directory for a project, and resolve its dependencies.
$ pkl project resolve
# Resolve dependencies for all projects within the `packages/` directory.
$ pkl project resolve packages/*/
```
"""
private val projectDirs: List<Path> by
argument("dir", "The project directories to resolve dependencies for").path().multiple()
override fun run() {
CliProjectResolver(baseOptions.baseOptions(emptyList()), projectDirs).run()
}
}
class PackageCommand : BaseCommand(name = "package", helpLink = helpLink) {
override val helpString =
"""
Verify package(s), and prepare package artifacts to be published.
This command runs a project's api tests, as defined by `apiTests` in `PklProject`.
Additionally, it verifies that all imports resolve to paths that are local to the project.
Finally, this command writes the following artifacts into the output directory specified by the output path.
- `name@version` - dependency metadata$NEWLINE
- `name@version.sha256` - dependency metadata's SHA-256 checksum$NEWLINE
- `name@version.zip` - package archive$NEWLINE
- `name@version.zip.sha256` - package archive's SHA-256 checksum
The output path option accepts the following placeholders:
- %{name}: The display name of the package$NEWLINE
- %{version}: The version of the package
If a project has local project dependencies, the depended upon project directories must also
be included as arguments to this command.
Examples:
```
# Search the current working directory for a project, and package it.
$ pkl project package
# Package all projects within the `packages/` directory.
$ pkl project package packages/*/
```
"""
.trimIndent()
private val testOptions by TestOptions()
private val projectDirs: List<Path> by
argument("dir", "The project directories to package").path().multiple()
private val outputPath: String by
option(
names = arrayOf("--output-path"),
help = "The directory to write artifacts to",
metavar = "path",
)
.single()
.default(".out/%{name}@%{version}")
private val skipPublishCheck: Boolean by
option(
names = arrayOf("--skip-publish-check"),
help = "Skip checking if a package has already been published with different contents",
)
.single()
.flag()
override fun run() {
CliProjectPackager(
baseOptions.baseOptions(emptyList()),
projectDirs,
testOptions.cliTestOptions,
outputPath,
skipPublishCheck,
)
.run()
subcommands(ResolveCommand(helpLink), PackageCommand(helpLink))
}
companion object {
class ResolveCommand(helpLink: String) :
BaseCommand(
name = "resolve",
helpLink = helpLink,
help =
"""
Resolve dependencies for project(s)
This command takes the `dependencies` of `PklProject`s, and writes the
resolved versions to `PklProject.deps.json` files.
Examples:
```
# Search the current working directory for a project, and resolve its dependencies.
$ pkl project resolve
# Resolve dependencies for all projects within the `packages/` directory.
$ pkl project resolve packages/*/
```
""",
) {
private val projectDirs: List<Path> by
argument("<dir>", "The project directories to resolve dependencies for").path().multiple()
override fun run() {
CliProjectResolver(baseOptions.baseOptions(emptyList()), projectDirs).run()
}
}
private const val NEWLINE = '\u0085'
class PackageCommand(helpLink: String) :
BaseCommand(
name = "package",
helpLink = helpLink,
help =
"""
Verify package(s), and prepare package artifacts to be published.
This command runs a project's api tests, as defined by `apiTests` in `PklProject`.
Additionally, it verifies that all imports resolve to paths that are local to the project.
Finally, this command writes the following artifacts into the output directory specified by the output path.
- `name@version` - dependency metadata$NEWLINE
- `name@version.sha256` - dependency metadata's SHA-256 checksum$NEWLINE
- `name@version.zip` - package archive$NEWLINE
- `name@version.zip.sha256` - package archive's SHA-256 checksum
The output path option accepts the following placeholders:
- %{name}: The display name of the package$NEWLINE
- %{version}: The version of the package
If a project has local project dependencies, the depended upon project directories must also
be included as arguments to this command.
Examples:
```
# Search the current working directory for a project, and package it.
$ pkl project package
# Package all projects within the `packages/` directory.
$ pkl project package packages/*/
```
"""
.trimIndent(),
) {
private val testOptions by TestOptions()
private val projectDirs: List<Path> by
argument("<dir>", "The project directories to package").path().multiple()
private val outputPath: String by
option(
names = arrayOf("--output-path"),
help = "The directory to write artifacts to",
metavar = "<path>"
)
.single()
.default(".out/%{name}@%{version}")
private val skipPublishCheck: Boolean by
option(
names = arrayOf("--skip-publish-check"),
help = "Skip checking if a package has already been published with different contents",
)
.single()
.flag()
override fun run() {
CliProjectPackager(
baseOptions.baseOptions(emptyList()),
projectDirs,
testOptions.cliTestOptions,
outputPath,
skipPublishCheck
)
.run()
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,9 +21,12 @@ import org.pkl.cli.CliRepl
import org.pkl.commons.cli.commands.BaseCommand
import org.pkl.commons.cli.commands.ProjectOptions
class ReplCommand : BaseCommand(name = "repl", helpLink = helpLink) {
override val helpString = "Start a REPL session"
class ReplCommand(helpLink: String) :
BaseCommand(
name = "repl",
help = "Start a REPL session",
helpLink = helpLink,
) {
private val projectOptions by ProjectOptions()
override fun run() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,39 +15,25 @@
*/
package org.pkl.cli.commands
import com.github.ajalt.clikt.core.Context
import com.github.ajalt.clikt.core.NoOpCliktCommand
import com.github.ajalt.clikt.core.context
import com.github.ajalt.clikt.core.subcommands
import org.pkl.commons.cli.commands.installCommonOptions
import org.pkl.core.Release
internal val helpLink = "${Release.current().documentation.homepage}pkl-cli/index.html#usage"
class RootCommand : NoOpCliktCommand(name = "pkl") {
override val printHelpOnEmptyArgs = true
override fun helpEpilog(context: Context) = "For more information, visit $helpLink"
import com.github.ajalt.clikt.parameters.options.versionOption
class RootCommand(name: String, version: String, helpLink: String) :
NoOpCliktCommand(
name = name,
printHelpOnEmptyArgs = true,
epilog = "For more information, visit $helpLink",
) {
init {
versionOption(version, names = setOf("-v", "--version"), message = { it })
context {
suggestTypoCorrection = { given, possible ->
correctionSuggestor = { given, possible ->
if (!given.startsWith("-")) {
registeredSubcommands().map { it.commandName }
} else possible
}
}
installCommonOptions()
subcommands(
EvalCommand(),
ReplCommand(),
ServerCommand(),
TestCommand(),
ProjectCommand(),
DownloadPackageCommand(),
AnalyzeCommand(),
)
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,15 +16,15 @@
package org.pkl.cli.commands
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.Context
import org.pkl.cli.CliServer
import org.pkl.commons.cli.CliBaseOptions
class ServerCommand : CliktCommand(name = "server") {
override fun help(context: Context) =
"Run as a server that communicates over standard input/output"
override fun helpEpilog(context: Context) = "For more information, visit $helpLink"
class ServerCommand(helpLink: String) :
CliktCommand(
name = "server",
help = "Run as a server that communicates over standard input/output",
epilog = "For more information, visit $helpLink"
) {
override fun run() {
CliServer(CliBaseOptions()).run()

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,11 +26,10 @@ import org.pkl.commons.cli.commands.BaseOptions
import org.pkl.commons.cli.commands.ProjectOptions
import org.pkl.commons.cli.commands.TestOptions
class TestCommand : BaseCommand(name = "test", helpLink = helpLink) {
override val helpString = "Run tests within the given module(s)"
class TestCommand(helpLink: String) :
BaseCommand(name = "test", help = "Run tests within the given module(s)", helpLink = helpLink) {
val modules: List<URI> by
argument(name = "modules", help = "Module paths or URIs to evaluate.")
argument(name = "<modules>", help = "Module paths or URIs to evaluate.")
.convert { BaseOptions.parseModuleName(it) }
.multiple()
@@ -41,7 +40,7 @@ class TestCommand : BaseCommand(name = "test", helpLink = helpLink) {
override fun run() {
CliTestRunner(
options = baseOptions.baseOptions(modules, projectOptions),
testOptions = testOptions.cliTestOptions,
testOptions = testOptions.cliTestOptions
)
.run()
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@ internal class Repl(workingDir: Path, private val server: ReplServer) {
option(Option.DISABLE_EVENT_EXPANSION, true)
variable(
org.jline.reader.LineReader.HISTORY_FILE,
(IoUtils.getPklHomeDir().resolve("repl-history")),
(IoUtils.getPklHomeDir().resolve("repl-history"))
)
}
.build()

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ private val cmdRegex = Regex(":(\\p{Alpha}*)(\\p{Space}*)(.*)", RegexOption.DOT_
internal fun getMatchingCommands(input: String): List<ParsedCommand> {
val match = cmdRegex.matchEntire(input) ?: return listOf()
val (cmd, ws, arg) = match.destructured
return Command.entries
return Command.values()
.filter { it.toString().lowercase().startsWith(cmd) }
.map { ParsedCommand(it, cmd, ws, arg) }
}
@@ -29,7 +29,7 @@ internal data class ParsedCommand(
val type: Command,
val cmd: String,
val ws: String,
val arg: String,
val arg: String
)
internal enum class Command {

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@ internal abstract class JLineFileNameCompleter : Completer {
override fun complete(
reader: LineReader,
commandLine: ParsedLine,
candidates: MutableList<Candidate>,
candidates: MutableList<Candidate>
) {
val buffer = commandLine.word().substring(0, commandLine.wordCursor())
val current: Path
@@ -78,7 +78,7 @@ internal abstract class JLineFileNameCompleter : Completer {
null,
if (reader.isSet(LineReader.Option.AUTO_REMOVE_SLASH)) sep else null,
null,
false,
false
)
)
} else {
@@ -90,7 +90,7 @@ internal abstract class JLineFileNameCompleter : Completer {
null,
null,
null,
true,
true
)
)
}
@@ -122,7 +122,7 @@ internal abstract class JLineFileNameCompleter : Completer {
terminal: Terminal,
path: Path,
resolver: StyleResolver,
separator: String,
separator: String
): String {
val builder = AttributedStringBuilder()
val name = path.fileName.toString()
@@ -162,7 +162,7 @@ internal class FileCompleter(override val userDir: Path) : JLineFileNameComplete
override fun complete(
reader: LineReader,
commandLine: ParsedLine,
candidates: MutableList<Candidate>,
candidates: MutableList<Candidate>
) {
val loadCmd =
getMatchingCommands(commandLine.line()).find { it.type == Command.Load && it.ws.isNotEmpty() }
@@ -174,7 +174,7 @@ internal class FileCompleter(override val userDir: Path) : JLineFileNameComplete
internal object CommandCompleter : Completer {
private val commandCandidates: List<Candidate> =
Command.entries.map { Candidate(":" + it.toString().lowercase()) }
Command.values().map { Candidate(":" + it.toString().lowercase()) }
override fun complete(reader: LineReader, line: ParsedLine, candidates: MutableList<Candidate>) {
if (line.wordIndex() == 0) candidates.addAll(commandCandidates)

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,7 +49,6 @@ import org.pkl.core.OutputFormat
import org.pkl.core.SecurityManagers
import org.pkl.core.util.IoUtils
@OptIn(ExperimentalPathApi::class)
@WireMockTest(httpsEnabled = true, proxyMode = true)
class CliEvaluatorTest {
companion object {
@@ -89,20 +88,19 @@ class CliEvaluatorTest {
val sourceFiles = listOf(writePklFile("test.pkl"))
val outputFiles =
evalToFiles(
CliEvaluatorOptions(CliBaseOptions(sourceModules = sourceFiles), outputFormat = "pcf")
CliEvaluatorOptions(
CliBaseOptions(sourceModules = sourceFiles),
outputFormat = "pcf",
)
)
assertThat(outputFiles).hasSize(1)
checkOutputFile(
outputFiles[0],
"test.pcf",
"""
checkOutputFile(outputFiles[0], "test.pcf", """
person {
name = "pigeon"
age = 30
}
""",
)
""")
}
@Test
@@ -110,7 +108,10 @@ person {
val sourceFiles = listOf(writePklFile("test.pkl"))
val outputFiles =
evalToFiles(
CliEvaluatorOptions(CliBaseOptions(sourceModules = sourceFiles), outputFormat = "json")
CliEvaluatorOptions(
CliBaseOptions(sourceModules = sourceFiles),
outputFormat = "json",
)
)
assertThat(outputFiles).hasSize(1)
@@ -124,7 +125,7 @@ person {
"age": 30
}
}
""",
"""
)
}
@@ -133,19 +134,18 @@ person {
val sourceFiles = listOf(writePklFile("test.pkl"))
val outputFiles =
evalToFiles(
CliEvaluatorOptions(CliBaseOptions(sourceModules = sourceFiles), outputFormat = "yaml")
CliEvaluatorOptions(
CliBaseOptions(sourceModules = sourceFiles),
outputFormat = "yaml",
)
)
assertThat(outputFiles).hasSize(1)
checkOutputFile(
outputFiles[0],
"test.yaml",
"""
checkOutputFile(outputFiles[0], "test.yaml", """
person:
name: pigeon
age: 30
""",
)
""")
}
@Test
@@ -153,7 +153,10 @@ person:
val sourceFiles = listOf(writePklFile("test.pkl"))
val outputFiles =
evalToFiles(
CliEvaluatorOptions(CliBaseOptions(sourceModules = sourceFiles), outputFormat = "plist")
CliEvaluatorOptions(
CliBaseOptions(sourceModules = sourceFiles),
outputFormat = "plist",
)
)
assertThat(outputFiles).hasSize(1)
@@ -175,7 +178,7 @@ person:
</dict>
</dict>
</plist>
""",
"""
)
}
@@ -184,7 +187,10 @@ person:
val sourceFiles = listOf(writePklFile("test.pkl"))
val outputFiles =
evalToFiles(
CliEvaluatorOptions(CliBaseOptions(sourceModules = sourceFiles), outputFormat = "xml")
CliEvaluatorOptions(
CliBaseOptions(sourceModules = sourceFiles),
outputFormat = "xml",
)
)
assertThat(outputFiles).hasSize(1)
@@ -199,7 +205,7 @@ person:
<age>30</age>
</person>
</root>
""",
"""
)
}
@@ -223,11 +229,14 @@ person:
listOf(
writePklFile("file1.pkl", "x = 1 + 1"),
writePklFile("file2.pkl", "x = 2 + 2"),
writePklFile("file3.pkl", "x = 3 + 3"),
writePklFile("file3.pkl", "x = 3 + 3")
)
val outputFiles =
evalToFiles(
CliEvaluatorOptions(CliBaseOptions(sourceModules = sourceFiles), outputFormat = "pcf")
CliEvaluatorOptions(
CliBaseOptions(sourceModules = sourceFiles),
outputFormat = "pcf",
)
)
assertThat(outputFiles).hasSize(3)
@@ -260,24 +269,20 @@ person:
CliBaseOptions(
sourceModules =
listOf(URI("modulepath:/foo/bar/test.pkl"), URI("modulepath:/foo/bar/test2.pkl")),
modulePath = listOf(tempDir),
modulePath = listOf(tempDir)
),
outputFormat = "pcf",
outputPath = "$tempDir/%{moduleName}.%{outputFormat}",
outputPath = "$tempDir/%{moduleName}.%{outputFormat}"
)
)
assertThat(outputFiles).hasSize(2)
checkOutputFile(
outputFiles[0],
"test.pcf",
"""
checkOutputFile(outputFiles[0], "test.pcf", """
person {
name = "pigeon"
age = 30
}
""",
)
""")
checkOutputFile(
outputFiles[1],
"test2.pcf",
@@ -286,7 +291,7 @@ person {
name = "barn owl"
age = 30
}
""",
"""
)
}
@@ -301,7 +306,7 @@ person {
name = read("prop:name")
age = read("prop:age").toInt()
}
""",
"""
)
)
@@ -310,23 +315,19 @@ person {
CliEvaluatorOptions(
CliBaseOptions(
sourceModules = sourceFiles,
externalProperties = mapOf("name" to "pigeon", "age" to "30"),
externalProperties = mapOf("name" to "pigeon", "age" to "30")
),
outputFormat = "pcf",
)
)
assertThat(outputFiles).hasSize(1)
checkOutputFile(
outputFiles[0],
"test.pcf",
"""
checkOutputFile(outputFiles[0], "test.pcf", """
person {
name = "pigeon"
age = 30
}
""",
)
""")
}
@Test
@@ -350,25 +351,21 @@ person {
sourceModules = listOf(file.toUri()),
workingDir =
if (relativePath) IoUtils.getCurrentWorkingDir().relativize(dir.parent)
else dir.parent,
else dir.parent
),
outputFormat = "pcf",
outputPath = "baz/%{moduleName}.pcf",
outputPath = "baz/%{moduleName}.pcf"
)
)
assertThat(outputFiles).hasSize(1)
assertThat(outputFiles[0].normalize()).isEqualTo(dir.parent.resolve("baz/test.pcf"))
checkOutputFile(
outputFiles[0],
"test.pcf",
"""
checkOutputFile(outputFiles[0], "test.pcf", """
person {
name = "pigeon"
age = 30
}
""",
)
""")
}
@Test
@@ -380,21 +377,17 @@ person {
evalToFiles(
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(URI("foo/test.pkl")), workingDir = tempDir),
outputFormat = "pcf",
outputFormat = "pcf"
)
)
assertThat(outputFiles).hasSize(1)
checkOutputFile(
outputFiles[0],
"test.pcf",
"""
checkOutputFile(outputFiles[0], "test.pcf", """
person {
name = "pigeon"
age = 30
}
""",
)
""")
}
@Test
@@ -403,13 +396,10 @@ person {
libDir.resolve("someLib.pkl").writeString("x = 1")
val pklScript =
writePklFile(
"test.pkl",
"""
writePklFile("test.pkl", """
import "modulepath:/foo/someLib.pkl"
result = someLib.x
""",
)
""")
val outputFiles =
evalToFiles(
@@ -417,9 +407,9 @@ result = someLib.x
CliBaseOptions(
sourceModules = listOf(pklScript),
workingDir = tempDir,
modulePath = listOf("lib".toPath()),
modulePath = listOf("lib".toPath())
),
outputFormat = "pcf",
outputFormat = "pcf"
)
)
@@ -437,7 +427,7 @@ result = someLib.x
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(file), workingDir = workingDir),
outputPath = "%{moduleDir}/result.pcf",
outputFormat = "pcf",
outputFormat = "pcf"
)
)
assertThat(outputFiles).hasSize(1)
@@ -459,7 +449,7 @@ result = someLib.x
evalToFiles(
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(file), workingDir = workingDir),
outputFormat = "pcf",
outputFormat = "pcf"
)
)
assertThat(outputFiles).hasSize(1)
@@ -475,10 +465,10 @@ result = someLib.x
CliEvaluator(
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(URI("repl:text"))),
outputFormat = "pcf",
outputFormat = "pcf"
),
stdin,
stdout,
stdout
)
evaluator.run()
assertThat(stdout.toString().trim()).isEqualTo(defaultContents.replace("20 + 10", "30").trim())
@@ -490,7 +480,11 @@ result = someLib.x
val module2 = writePklFile("mod2.pkl", "y = 11 + 11")
val output =
evalToConsole(CliEvaluatorOptions(CliBaseOptions(sourceModules = listOf(module1, module2))))
evalToConsole(
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(module1, module2)),
)
)
assertThat(output).isEqualTo("x = 42\n---\ny = 22\n")
}
@@ -504,7 +498,7 @@ result = someLib.x
"""
function fib(n) = if (n < 2) 0 else fib(n - 1) + fib(n - 2)
x = fib(100)
""",
"""
)
)
@@ -513,7 +507,7 @@ result = someLib.x
evalToFiles(
CliEvaluatorOptions(
CliBaseOptions(sourceModules = sourceFiles, timeout = Duration.ofMillis(100)),
outputFormat = "pcf",
outputFormat = "pcf"
)
)
}
@@ -522,20 +516,16 @@ result = someLib.x
@Test
fun `cannot import module located outside root dir`() {
val sourceFiles =
listOf(
writePklFile(
"test.pkl",
"""
val sourceFiles = listOf(writePklFile("test.pkl", """
amends "/non/existing.pkl"
""",
)
)
"""))
val e =
assertThrows<CliException> {
evalToFiles(
CliEvaluatorOptions(CliBaseOptions(sourceModules = sourceFiles, rootDir = tempDir))
CliEvaluatorOptions(
CliBaseOptions(sourceModules = sourceFiles, rootDir = tempDir),
)
)
}
@@ -548,7 +538,7 @@ result = someLib.x
listOf(
writePklFile("test1.pkl", "x = 1"),
writePklFile("test2.pkl", "x = 2"),
writePklFile("test3.pkl", "x = 3"),
writePklFile("test3.pkl", "x = 3")
)
val outputFile = tempDir.resolve("output.yaml")
@@ -557,7 +547,7 @@ result = someLib.x
CliEvaluatorOptions(
CliBaseOptions(sourceModules = sourceFiles),
outputFile.toString(),
"yaml",
"yaml"
)
)
@@ -570,18 +560,18 @@ result = someLib.x
listOf(
writePklFile(
"test0.pkl",
"output { value = List(); renderer = new YamlRenderer { isStream = true } }",
"output { value = List(); renderer = new YamlRenderer { isStream = true } }"
),
writePklFile("test1.pkl", "x = 1"),
writePklFile(
"test2.pkl",
"output { value = List(); renderer = new YamlRenderer { isStream = true } }",
"output { value = List(); renderer = new YamlRenderer { isStream = true } }"
),
writePklFile("test3.pkl", "x = 3"),
writePklFile(
"test4.pkl",
"output { value = List(); renderer = new YamlRenderer { isStream = true } }",
),
"output { value = List(); renderer = new YamlRenderer { isStream = true } }"
)
)
val outputFile = tempDir.resolve("output.yaml")
@@ -590,7 +580,7 @@ result = someLib.x
CliEvaluatorOptions(
CliBaseOptions(sourceModules = sourceFiles),
outputFile.toString(),
"yaml",
"yaml"
)
)
@@ -603,7 +593,7 @@ result = someLib.x
listOf(
writePklFile("test1.pkl", "x = 1"),
writePklFile("test2.pkl", "x = 2"),
writePklFile("test3.pkl", "x = 3"),
writePklFile("test3.pkl", "x = 3")
)
val outputFile = tempDir.resolve("output.pcf")
@@ -613,7 +603,7 @@ result = someLib.x
CliBaseOptions(sourceModules = sourceFiles),
outputFile.toString(),
outputFormat = "pcf",
moduleOutputSeparator = "// my module separator",
moduleOutputSeparator = "// my module separator"
)
)
@@ -627,7 +617,7 @@ result = someLib.x
// my module separator
x = 3
"""
.trimIndent(),
.trimIndent()
)
}
@@ -637,7 +627,7 @@ result = someLib.x
listOf(
writePklFile("test1.pkl", "x = 1"),
writePklFile("test2.pkl", "y = 2"),
writePklFile("test3.pkl", "z = 3"),
writePklFile("test3.pkl", "z = 3")
)
val outputFile = tempDir.resolve("output.pcf")
@@ -647,7 +637,7 @@ result = someLib.x
CliBaseOptions(sourceModules = sourceFiles),
outputFile.toString(),
outputFormat = "pcf",
moduleOutputSeparator = "",
moduleOutputSeparator = ""
)
)
@@ -661,7 +651,7 @@ result = someLib.x
z = 3
"""
.trimIndent(),
.trimIndent()
)
}
@@ -671,13 +661,11 @@ result = someLib.x
listOf(
writePklFile("test1.pkl", "x = 1"),
writePklFile("test2.pkl", "x = 2"),
writePklFile("test3.pkl", "x = 3"),
writePklFile("test3.pkl", "x = 3")
)
val output =
evalToConsole(
CliEvaluatorOptions(CliBaseOptions(sourceModules = sourceFiles), outputFormat = "yaml")
)
evalToConsole(CliEvaluatorOptions(CliBaseOptions(sourceModules = sourceFiles), null, "yaml"))
assertThat(output).isEqualTo("x: 1\n---\nx: 2\n---\nx: 3\n")
}
@@ -688,24 +676,22 @@ result = someLib.x
listOf(
writePklFile(
"test0.pkl",
"output { value = List(); renderer = new YamlRenderer { isStream = true } }",
"output { value = List(); renderer = new YamlRenderer { isStream = true } }"
),
writePklFile("test1.pkl", "x = 1"),
writePklFile(
"test2.pkl",
"output { value = List(); renderer = new YamlRenderer { isStream = true } }",
"output { value = List(); renderer = new YamlRenderer { isStream = true } }"
),
writePklFile("test3.pkl", "x = 3"),
writePklFile(
"test4.pkl",
"output { value = List(); renderer = new YamlRenderer { isStream = true } }",
),
"output { value = List(); renderer = new YamlRenderer { isStream = true } }"
)
)
val output =
evalToConsole(
CliEvaluatorOptions(CliBaseOptions(sourceModules = sourceFiles), outputFormat = "yaml")
)
evalToConsole(CliEvaluatorOptions(CliBaseOptions(sourceModules = sourceFiles), null, "yaml"))
assertThat(output).isEqualTo("x: 1\n---\nx: 3\n")
}
@@ -719,7 +705,8 @@ result = someLib.x
evalToConsole(
CliEvaluatorOptions(
CliBaseOptions(sourceModules = sourceFiles),
outputFormat = outputFormat.toString(),
null,
outputFormat.toString()
)
)
assertThat(output).endsWith("\n")
@@ -763,7 +750,7 @@ result = someLib.x
"""
["bar"] = "baz"
"""
.trimIndent(),
.trimIndent()
)
checkOutputFile(
tempDir.resolve(".my-output/bar/baz.pcf"),
@@ -771,7 +758,7 @@ result = someLib.x
"""
["baz"] = "biz"
"""
.trimIndent(),
.trimIndent()
)
checkOutputFile(tempDir.resolve(".my-output/buz.txt"), "buz.txt", "buz")
}
@@ -809,7 +796,7 @@ result = someLib.x
}
"""
.trimIndent(),
),
)
)
val options =
CliEvaluatorOptions(
@@ -836,7 +823,7 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
),
writePklFile(
"foo.pkl",
@@ -849,7 +836,7 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
),
)
val options =
@@ -862,7 +849,11 @@ result = someLib.x
@Test
fun `multiple file output writes nothing if output files is null`() {
val moduleUri = writePklFile("test.pkl", "")
val moduleUri =
writePklFile(
"test.pkl",
"",
)
val options =
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(moduleUri), workingDir = tempDir),
@@ -887,12 +878,12 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
)
val options =
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(moduleUri), workingDir = tempDir),
multipleFileOutputPath = ".output",
multipleFileOutputPath = ".output"
)
assertThatCode { evalToConsole(options) }
.hasMessageStartingWith("Output file conflict:")
@@ -913,7 +904,7 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
),
writePklFile(
"test2.pkl",
@@ -924,14 +915,14 @@ result = someLib.x
}
}
"""
.trimIndent(),
),
.trimIndent()
)
)
for (moduleUri in moduleUris) {
val options =
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(moduleUri), workingDir = tempDir),
multipleFileOutputPath = ".output",
multipleFileOutputPath = ".output"
)
assertThatCode { evalToConsole(options) }
.hasMessageStartingWith("Output file conflict:")
@@ -952,7 +943,7 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
),
writePklFile(
"test2.pkl",
@@ -963,13 +954,13 @@ result = someLib.x
}
}
"""
.trimIndent(),
),
.trimIndent()
)
)
val options =
CliEvaluatorOptions(
CliBaseOptions(sourceModules = moduleUris, workingDir = tempDir),
multipleFileOutputPath = ".output",
multipleFileOutputPath = ".output"
)
assertThatCode { evalToConsole(options) }
.hasMessageContaining("Output file conflict:")
@@ -989,12 +980,12 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
)
val options =
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(moduleUri), workingDir = tempDir),
multipleFileOutputPath = ".output",
multipleFileOutputPath = ".output"
)
assertThatCode { evalToConsole(options) }
.hasMessageContaining("Output file conflict:")
@@ -1014,13 +1005,13 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
)
val options =
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(moduleUri), workingDir = tempDir),
multipleFileOutputPath = ".output",
multipleFileOutputPath = ".output"
)
assertThatCode { evalToConsole(options) }
.hasMessageContaining("Path spec `foo:bar` contains illegal character `:`.")
@@ -1039,13 +1030,13 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
)
val options =
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(moduleUri), workingDir = tempDir),
multipleFileOutputPath = ".output",
multipleFileOutputPath = ".output"
)
assertThatCode { evalToConsole(options) }
.hasMessageContaining("Path spec `foo\\bar` contains illegal character `\\`.")
@@ -1061,7 +1052,7 @@ result = someLib.x
bar = 1
}
"""
.trimIndent(),
.trimIndent()
)
val options =
CliEvaluatorOptions(
@@ -1092,7 +1083,7 @@ result = someLib.x
}
person: Person = new { name = "Frodo" }
"""
.trimIndent(),
.trimIndent()
)
val options =
CliEvaluatorOptions(
@@ -1114,7 +1105,7 @@ result = someLib.x
friend { name = "Bilbo" }
}
"""
.trimIndent(),
.trimIndent()
)
val options =
CliEvaluatorOptions(
@@ -1134,7 +1125,7 @@ result = someLib.x
"""
res = 1
"""
.trimIndent(),
.trimIndent()
)
writePklFile(
"PklProject",
@@ -1143,11 +1134,11 @@ result = someLib.x
package = throw("invalid project package")
"""
.trimIndent(),
.trimIndent()
)
val options =
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(moduleUri), workingDir = tempDir, noProject = true)
CliBaseOptions(sourceModules = listOf(moduleUri), workingDir = tempDir, noProject = true),
)
val buffer = StringWriter()
CliEvaluator(options, consoleWriter = buffer).run()
@@ -1163,7 +1154,7 @@ result = someLib.x
"""
res = read*("env:**")
"""
.trimIndent(),
.trimIndent()
)
writePklFile(
"PklProject",
@@ -1178,10 +1169,12 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
)
val options =
CliEvaluatorOptions(CliBaseOptions(sourceModules = listOf(moduleUri), workingDir = tempDir))
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(moduleUri), workingDir = tempDir),
)
val buffer = StringWriter()
CliEvaluator(options, consoleWriter = buffer).run()
assertThat(buffer.toString())
@@ -1207,7 +1200,7 @@ result = someLib.x
res = Swallow
"""
.trimIndent(),
.trimIndent()
)
val buffer = StringWriter()
val options =
@@ -1218,8 +1211,8 @@ result = someLib.x
moduleCacheDir = tempDir,
noCache = true,
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = packageServer.port,
)
testPort = packageServer.port
),
)
CliEvaluator(options, consoleWriter = buffer).run()
assertThat(buffer.toString())
@@ -1249,7 +1242,7 @@ result = someLib.x
}
@Test
fun `gives decent error message if certificate file is empty`(@TempDir tempDir: Path) {
fun `gives decent error message if certificate file is emtpy`(@TempDir tempDir: Path) {
val emptyCerts = tempDir.writeEmptyFile("empty.pem")
val err = assertThrows<CliException> { evalModuleThatImportsPackage(emptyCerts) }
assertThat(err).hasMessageContaining("CA certificate file `${emptyCerts.pathString}` is empty.")
@@ -1285,7 +1278,7 @@ result = someLib.x
sourceModules = listOf(URI("http://not.a.valid.host/bar.pkl")),
httpProxy = URI("http://localhost:${wwRuntimeInfo.httpPort}"),
allowedModules = SecurityManagers.defaultAllowedModules + Pattern.compile("http:"),
)
),
)
val output = evalToConsole(options)
assertThat(output).isEqualTo("foo = 1\n")
@@ -1320,18 +1313,18 @@ result = someLib.x
val options =
CliEvaluatorOptions(
CliBaseOptions(
sourceModules = listOf(URI("package://localhost:1/birds@0.5.0#/catalog/Ostrich.pkl")),
sourceModules = listOf(URI("package://localhost:1/birds@0.5.0#/catalog/Ostritch.pkl")),
noCache = true,
httpProxy = URI(wwRuntimeInfo.httpBaseUrl),
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
allowedModules = SecurityManagers.defaultAllowedModules + Pattern.compile("http:"),
allowedModules = SecurityManagers.defaultAllowedModules + Pattern.compile("http:")
)
)
val output = evalToConsole(options)
assertThat(output)
.isEqualTo(
"""
name = "Ostrich"
name = "Ostritch"
favoriteFruit {
name = "Orange"
@@ -1347,7 +1340,7 @@ result = someLib.x
@Test
fun `eval http module from proxy -- configured in settings`(
@TempDir tempDir: Path,
wwRuntimeInfo: WireMockRuntimeInfo,
wwRuntimeInfo: WireMockRuntimeInfo
) {
val settingsModule =
tempDir.writeFile(
@@ -1361,7 +1354,7 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
)
stubFor(
@@ -1373,7 +1366,7 @@ result = someLib.x
sourceModules = listOf(URI("http://not.a.valid.host/bar.pkl")),
settings = settingsModule.toUri(),
allowedModules = SecurityManagers.defaultAllowedModules + Pattern.compile("http:"),
)
),
)
val output = evalToConsole(options)
assertThat(output).isEqualTo("foo = 1\n")
@@ -1382,7 +1375,7 @@ result = someLib.x
@Test
fun `eval http module from proxy -- configured in PklProject`(
@TempDir tempDir: Path,
wwRuntimeInfo: WireMockRuntimeInfo,
wwRuntimeInfo: WireMockRuntimeInfo
) {
tempDir.writeFile(
"PklProject",
@@ -1397,7 +1390,7 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
)
stubFor(
@@ -1408,8 +1401,8 @@ result = someLib.x
CliBaseOptions(
sourceModules = listOf(URI("http://not.a.valid.host/bar.pkl")),
allowedModules = SecurityManagers.defaultAllowedModules + Pattern.compile("http:"),
projectDir = tempDir,
)
projectDir = tempDir
),
)
val output = evalToConsole(options)
assertThat(output).isEqualTo("foo = 1\n")
@@ -1418,7 +1411,7 @@ result = someLib.x
@Test
fun `eval http module from proxy -- PklProject beats user settings`(
@TempDir tempDir: Path,
wwRuntimeInfo: WireMockRuntimeInfo,
wwRuntimeInfo: WireMockRuntimeInfo
) {
val projectDir = tempDir.resolve("my-project")
projectDir.writeFile(
@@ -1434,7 +1427,7 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
)
val homeDir = tempDir.resolve("my-home")
homeDir.writeFile(
@@ -1448,7 +1441,7 @@ result = someLib.x
}
}
"""
.trimIndent(),
.trimIndent()
)
val options =
CliEvaluatorOptions(
@@ -1456,8 +1449,8 @@ result = someLib.x
sourceModules = listOf(URI("http://not.a.valid.host/bar.pkl")),
allowedModules = SecurityManagers.defaultAllowedModules + Pattern.compile("http:"),
projectDir = projectDir,
settings = homeDir.resolve("settings.pkl").toUri(),
)
settings = homeDir.resolve("settings.pkl").toUri()
),
)
stubFor(get(anyUrl()).willReturn(ok("result = 1")))
val output = evalToConsole(options)
@@ -1484,9 +1477,14 @@ result = someLib.x
importGlob = import*("./日*.pkl").keys
importGlobFile = import*("$tempDirUri**/*.pkl").keys.map((it) -> it.replaceAll("$tempDirUri".replaceAll("///", "/"), ""))
"""
.trimIndent(),
.trimIndent()
)
val output =
evalToConsole(
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(file)),
)
)
val output = evalToConsole(CliEvaluatorOptions(CliBaseOptions(sourceModules = listOf(file))))
val tripleQuote = "\"\"\""
assertThat(output)
@@ -1523,7 +1521,7 @@ result = someLib.x
import "package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"
res = Swallow
""",
"""
)
val options =
@@ -1533,8 +1531,8 @@ result = someLib.x
caCertificates = buildList { if (certsFile != null) add(certsFile) },
workingDir = tempDir,
noCache = true,
testPort = testPort,
)
testPort = testPort
),
)
CliEvaluator(options).run()
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,7 +65,7 @@ class CliImportAnalyzerTest {
val analyzer =
CliImportAnalyzer(
CliImportAnalyzerOptions(baseOptions, outputFormat = OutputFormat.JSON.toString()),
StringBuilderWriter(sb),
StringBuilderWriter(sb)
)
analyzer.run()
assertThat(sb.toString())

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,7 @@
package org.pkl.cli
import com.github.ajalt.clikt.core.BadParameterValue
import com.github.ajalt.clikt.core.CliktError
import com.github.ajalt.clikt.core.parse
import com.github.ajalt.clikt.core.subcommands
import java.nio.file.Path
import kotlin.io.path.createDirectory
import kotlin.io.path.createSymbolicLinkPointingTo
@@ -28,37 +27,35 @@ import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.condition.DisabledOnOs
import org.junit.jupiter.api.condition.OS
import org.junit.jupiter.api.io.TempDir
import org.pkl.cli.commands.AnalyzeCommand
import org.pkl.cli.commands.EvalCommand
import org.pkl.cli.commands.RootCommand
import org.pkl.commons.writeString
import org.pkl.core.Release
class CliMainTest {
private val rootCmd = RootCommand()
private val evalCmd = EvalCommand("")
private val analyzeCommand = AnalyzeCommand("")
private val cmd = RootCommand("pkl", "pkl version 1", "").subcommands(evalCmd, analyzeCommand)
@Test
fun `duplicate CLI option produces meaningful error message`(@TempDir tempDir: Path) {
val inputFile = tempDir.resolve("test.pkl").writeString("").toString()
assertThatCode {
rootCmd.parse(
arrayOf("eval", "--output-path", "path1", "--output-path", "path2", inputFile)
)
cmd.parse(arrayOf("eval", "--output-path", "path1", "--output-path", "path2", inputFile))
}
.hasMessage("Option cannot be repeated")
.hasMessage("Invalid value for \"--output-path\": Option cannot be repeated")
assertThatCode {
rootCmd.parse(arrayOf("eval", "-o", "path1", "--output-path", "path2", inputFile))
cmd.parse(arrayOf("eval", "-o", "path1", "--output-path", "path2", inputFile))
}
.hasMessage("Option cannot be repeated")
.hasMessage("Invalid value for \"--output-path\": Option cannot be repeated")
}
@Test
fun `eval requires at least one file`() {
assertThatCode { rootCmd.parse(arrayOf("eval")) }
.isInstanceOf(CliktError::class.java)
.extracting("paramName")
.isEqualTo("modules")
assertThatCode { cmd.parse(arrayOf("eval")) }.hasMessage("""Missing argument "<modules>"""")
}
// Can't reliably create symlinks on Windows.
@@ -79,7 +76,7 @@ class CliMainTest {
val inputFile = tempDir.resolve("test.pkl").writeString(code).toString()
val outputFile = makeSymdir(tempDir, "out", "linkOut").resolve("test.pkl").toString()
assertThatCode { rootCmd.parse(arrayOf("eval", inputFile, "-o", outputFile)) }
assertThatCode { cmd.parse(arrayOf("eval", inputFile, "-o", outputFile)) }
.doesNotThrowAnyException()
}
@@ -87,26 +84,25 @@ class CliMainTest {
fun `cannot have multiple output with -o or -x`(@TempDir tempDir: Path) {
val testIn = makeInput(tempDir)
val testOut = tempDir.resolve("test").toString()
val error = """Option is mutually exclusive with -o, --output-path and -x, --expression."""
val error =
"""Invalid value for "--multiple-file-output-path": Option is mutually exclusive with -o, --output-path and -x, --expression."""
assertThatCode { rootCmd.parse(arrayOf("eval", "-m", testOut, "-x", "x", testIn)) }
assertThatCode { cmd.parse(arrayOf("eval", "-m", testOut, "-x", "x", testIn)) }
.hasMessage(error)
assertThatCode { rootCmd.parse(arrayOf("eval", "-m", testOut, "-o", "/tmp/test", testIn)) }
assertThatCode { cmd.parse(arrayOf("eval", "-m", testOut, "-o", "/tmp/test", testIn)) }
.hasMessage(error)
}
@Test
fun `showing version works`() {
assertThatCode { rootCmd.parse(arrayOf("--version")) }.hasMessage(Release.current().versionInfo)
assertThatCode { cmd.parse(arrayOf("--version")) }.hasMessage("pkl version 1")
}
@Test
fun `file paths get parsed into URIs`(@TempDir tempDir: Path) {
val cmd = RootCommand()
cmd.parse(arrayOf("eval", makeInput(tempDir, "my file.txt")))
val evalCmd = cmd.registeredSubcommands().filterIsInstance<EvalCommand>().first()
val modules = evalCmd.baseOptions.baseOptions(evalCmd.modules).normalizedSourceModules
assertThat(modules).hasSize(1)
assertThat(modules[0].path).endsWith("my file.txt")
@@ -114,7 +110,7 @@ class CliMainTest {
@Test
fun `invalid URIs are not accepted`() {
val ex = assertThrows<BadParameterValue> { rootCmd.parse(arrayOf("eval", "file:my file.txt")) }
val ex = assertThrows<BadParameterValue> { cmd.parse(arrayOf("eval", "file:my file.txt")) }
assertThat(ex.message).contains("URI `file:my file.txt` has invalid syntax")
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@ import org.pkl.core.packages.PackageUri
class CliPackageDownloaderTest {
companion object {
private val server = PackageServer()
val server = PackageServer()
@AfterAll
@JvmStatic
@@ -45,15 +45,15 @@ class CliPackageDownloaderTest {
CliBaseOptions(
moduleCacheDir = tempDir,
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = server.port,
testPort = server.port
),
packageUris =
listOf(
PackageUri("package://localhost:0/birds@0.5.0"),
PackageUri("package://localhost:0/fruit@1.0.5"),
PackageUri("package://localhost:0/fruit@1.1.0"),
PackageUri("package://localhost:0/fruit@1.1.0")
),
noTransitive = true,
noTransitive = true
)
cmd.run()
assertThat(tempDir.resolve("package-2/localhost(3a)0/birds@0.5.0/birds@0.5.0.zip")).exists()
@@ -75,7 +75,7 @@ class CliPackageDownloaderTest {
moduleCacheDir = ".my-cache"
}
"""
.trimIndent(),
.trimIndent()
)
val cmd =
@@ -84,10 +84,10 @@ class CliPackageDownloaderTest {
CliBaseOptions(
workingDir = tempDir,
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = server.port,
testPort = server.port
),
packageUris = listOf(PackageUri("package://localhost:0/birds@0.5.0")),
noTransitive = true,
noTransitive = true
)
cmd.run()
assertThat(tempDir.resolve(".my-cache/package-2/localhost(3a)0/birds@0.5.0/birds@0.5.0.zip"))
@@ -104,13 +104,13 @@ class CliPackageDownloaderTest {
CliBaseOptions(
moduleCacheDir = tempDir,
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = server.port,
testPort = server.port
),
packageUris =
listOf(
PackageUri("package://localhost:0/birds@0.5.0::sha256:${PackageServer.BIRDS_SHA}")
PackageUri("package://localhost:0/birds@0.5.0::sha256:${PackageServer.BIRDS_SHA}"),
),
noTransitive = true,
noTransitive = true
)
cmd.run()
assertThat(tempDir.resolve("package-2/localhost(3a)0/birds@0.5.0/birds@0.5.0.zip")).exists()
@@ -125,13 +125,13 @@ class CliPackageDownloaderTest {
CliBaseOptions(
moduleCacheDir = tempDir,
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = server.port,
testPort = server.port
),
packageUris =
listOf(
PackageUri("package://localhost:0/birds@0.5.0::sha256:intentionallyBogusChecksum")
PackageUri("package://localhost:0/birds@0.5.0::sha256:intentionallyBogusChecksum"),
),
noTransitive = true,
noTransitive = true
)
assertThatCode { cmd.run() }
.hasMessage(
@@ -152,7 +152,7 @@ class CliPackageDownloaderTest {
CliPackageDownloader(
baseOptions = CliBaseOptions(workingDir = tempDir, noCache = true),
packageUris = listOf(PackageUri("package://localhost:0/birds@0.5.0")),
noTransitive = true,
noTransitive = true
)
assertThatCode { cmd.run() }
.hasMessage("Cannot download packages because no cache directory is specified.")
@@ -166,10 +166,10 @@ class CliPackageDownloaderTest {
CliBaseOptions(
moduleCacheDir = tempDir,
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = server.port,
testPort = server.port
),
packageUris = listOf(PackageUri("package://localhost:0/badChecksum@1.0.0")),
noTransitive = true,
noTransitive = true
)
assertThatCode { cmd.run() }
.hasMessageStartingWith(
@@ -185,14 +185,14 @@ class CliPackageDownloaderTest {
CliBaseOptions(
moduleCacheDir = tempDir,
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = server.port,
testPort = server.port
),
packageUris =
listOf(
PackageUri("package://localhost:0/badChecksum@1.0.0"),
PackageUri("package://bogus.domain/notAPackage@1.0.0"),
PackageUri("package://bogus.domain/notAPackage@1.0.0")
),
noTransitive = true,
noTransitive = true
)
assertThatCode { cmd.run() }
.hasMessage(
@@ -222,10 +222,10 @@ class CliPackageDownloaderTest {
CliBaseOptions(
moduleCacheDir = tempDir,
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = server.port,
testPort = server.port
),
packageUris = listOf(PackageUri("package://localhost:0/birds@0.5.0")),
noTransitive = false,
noTransitive = false
)
.run()
assertThat(tempDir.resolve("package-2/localhost(3a)0/birds@0.5.0/birds@0.5.0.zip")).exists()

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -115,7 +115,7 @@ class CliProjectPackagerTest {
}
}
"""
.trimIndent(),
.trimIndent()
)
tempDir.writeFile(
"PklProject",
@@ -130,7 +130,7 @@ class CliProjectPackagerTest {
apiTests { "myTest.pkl" }
}
"""
.trimIndent(),
.trimIndent()
)
val buffer = StringWriter()
val packager =
@@ -140,7 +140,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = buffer,
consoleWriter = buffer
)
val err = assertThrows<CliException> { packager.run() }
assertThat(err).hasMessageContaining("because its API tests are failing")
@@ -187,7 +187,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = buffer,
consoleWriter = buffer
)
packager.run()
}
@@ -286,7 +286,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out",
skipPublishCheck = true,
consoleWriter = buffer,
consoleWriter = buffer
)
packager.run()
}
@@ -301,7 +301,7 @@ class CliProjectPackagerTest {
name: String
"""
.trimIndent(),
.trimIndent()
)
val fooTxt =
@@ -312,7 +312,7 @@ class CliProjectPackagerTest {
bar
baz
"""
.trimIndent(),
.trimIndent()
)
tempDir
@@ -337,7 +337,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = StringWriter(),
consoleWriter = StringWriter()
)
packager.run()
val expectedMetadata = tempDir.resolve(".out/mypackage@1.0.0/mypackage@1.0.0")
@@ -411,7 +411,7 @@ class CliProjectPackagerTest {
}
}
"""
.trimIndent(),
.trimIndent()
)
CliProjectPackager(
CliBaseOptions(workingDir = tempDir),
@@ -419,7 +419,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = StringWriter(),
consoleWriter = StringWriter()
)
.run()
val expectedArchive = tempDir.resolve(".out/mypackage@1.0.0/mypackage@1.0.0.zip")
@@ -432,7 +432,7 @@ class CliProjectPackagerTest {
"/input",
"/input/foo",
"/input/foo/bar.txt",
"/main.pkl",
"/main.pkl"
)
)
}
@@ -460,7 +460,7 @@ class CliProjectPackagerTest {
["project2"] = import("../project2/PklProject")
}
"""
.trimIndent(),
.trimIndent()
)
projectDir.writeFile(
"PklProject.deps.json",
@@ -483,7 +483,7 @@ class CliProjectPackagerTest {
}
}
"""
.trimIndent(),
.trimIndent()
)
project2Dir.writeFile(
@@ -498,7 +498,7 @@ class CliProjectPackagerTest {
packageZipUrl = "https://foo.com/project2.zip"
}
"""
.trimIndent(),
.trimIndent()
)
project2Dir.writeFile(
"PklProject.deps.json",
@@ -508,7 +508,7 @@ class CliProjectPackagerTest {
"resolvedDependencies": {}
}
"""
.trimIndent(),
.trimIndent()
)
CliProjectPackager(
@@ -517,7 +517,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = StringWriter(),
consoleWriter = StringWriter()
)
.run()
val expectedMetadata = tempDir.resolve(".out/mypackage@1.0.0/mypackage@1.0.0")
@@ -598,7 +598,7 @@ class CliProjectPackagerTest {
["project2"] = import("../project2/PklProject")
}
"""
.trimIndent(),
.trimIndent()
)
projectDir.writeFile(
"PklProject.deps.json",
@@ -621,7 +621,7 @@ class CliProjectPackagerTest {
}
}
"""
.trimIndent(),
.trimIndent()
)
project2Dir.writeFile(
@@ -636,7 +636,7 @@ class CliProjectPackagerTest {
packageZipUrl = "https://foo.com/project2.zip"
}
"""
.trimIndent(),
.trimIndent()
)
project2Dir.writeFile(
"PklProject.deps.json",
@@ -646,7 +646,7 @@ class CliProjectPackagerTest {
"resolvedDependencies": {}
}
"""
.trimIndent(),
.trimIndent()
)
assertThatCode {
CliProjectPackager(
@@ -655,7 +655,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = StringWriter(),
consoleWriter = StringWriter()
)
.run()
}
@@ -671,7 +671,7 @@ class CliProjectPackagerTest {
res = foo
"""
.trimIndent(),
.trimIndent()
)
tempDir.writeFile(
"PklProject",
@@ -685,7 +685,7 @@ class CliProjectPackagerTest {
packageZipUrl = "https://foo.com"
}
"""
.trimIndent(),
.trimIndent()
)
val e =
assertThrows<CliException> {
@@ -695,7 +695,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = StringWriter(),
consoleWriter = StringWriter()
)
.run()
}
@@ -725,7 +725,7 @@ class CliProjectPackagerTest {
res = foo
"""
.trimIndent(),
.trimIndent()
)
tempDir.writeFile(
"PklProject",
@@ -739,7 +739,7 @@ class CliProjectPackagerTest {
packageZipUrl = "https://foo.com"
}
"""
.trimIndent(),
.trimIndent()
)
val e =
assertThrows<CliException> {
@@ -749,7 +749,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = StringWriter(),
consoleWriter = StringWriter()
)
.run()
}
@@ -771,7 +771,7 @@ class CliProjectPackagerTest {
"""
res = read("$tempDir/foo.pkl")
"""
.trimIndent(),
.trimIndent()
)
tempDir.writeFile(
"PklProject",
@@ -785,7 +785,7 @@ class CliProjectPackagerTest {
packageZipUrl = "https://foo.com"
}
"""
.trimIndent(),
.trimIndent()
)
val e =
assertThrows<CliException> {
@@ -795,7 +795,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = StringWriter(),
consoleWriter = StringWriter()
)
.run()
}
@@ -816,7 +816,7 @@ class CliProjectPackagerTest {
"""
import "baz.pkl"
"""
.trimIndent(),
.trimIndent()
)
tempDir.writeFile(
"PklProject",
@@ -830,7 +830,7 @@ class CliProjectPackagerTest {
packageZipUrl = "https://foo.com"
}
"""
.trimIndent(),
.trimIndent()
)
CliProjectPackager(
CliBaseOptions(workingDir = tempDir),
@@ -838,7 +838,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = StringWriter(),
consoleWriter = StringWriter()
)
.run()
}
@@ -858,7 +858,7 @@ class CliProjectPackagerTest {
packageZipUrl = "https://foo.com"
}
"""
.trimIndent(),
.trimIndent()
)
tempDir.writeFile("project2/main2.pkl", "res = 2")
tempDir.writeFile(
@@ -873,7 +873,7 @@ class CliProjectPackagerTest {
packageZipUrl = "https://foo.com"
}
"""
.trimIndent(),
.trimIndent()
)
val out = StringWriter()
CliProjectPackager(
@@ -882,7 +882,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = out,
consoleWriter = out
)
.run()
val sep = File.separatorChar
@@ -923,7 +923,7 @@ class CliProjectPackagerTest {
packageZipUrl = "https://foo.com"
}
"""
.trimIndent(),
.trimIndent()
)
val e =
assertThrows<CliException> {
@@ -931,13 +931,13 @@ class CliProjectPackagerTest {
CliBaseOptions(
workingDir = tempDir,
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = packageServer.port,
testPort = packageServer.port
),
listOf(tempDir.resolve("project")),
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = false,
consoleWriter = StringWriter(),
consoleWriter = StringWriter()
)
.run()
}
@@ -968,20 +968,20 @@ class CliProjectPackagerTest {
packageZipUrl = "https://foo.com"
}
"""
.trimIndent(),
.trimIndent()
)
val out = StringWriter()
CliProjectPackager(
CliBaseOptions(
workingDir = tempDir,
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = packageServer.port,
testPort = packageServer.port
),
listOf(tempDir.resolve("project")),
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = false,
consoleWriter = out,
consoleWriter = out
)
.run()
val sep = File.separatorChar
@@ -1025,7 +1025,7 @@ class CliProjectPackagerTest {
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = StringWriter(),
consoleWriter = StringWriter()
)
packager.run()
val expectedMetadata = tempDir.resolve(".out/mypackage@1.0.0/mypackage@1.0.0")

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@ class CliProjectResolverTest {
CliBaseOptions(workingDir = tempDir, noCache = true),
emptyList(),
consoleWriter = StringWriter(),
errWriter = StringWriter(),
errWriter = StringWriter()
)
val err = assertThrows<CliException> { packager.run() }
assertThat(err).hasMessageStartingWith("No project visible to the working directory.")
@@ -60,7 +60,7 @@ class CliProjectResolverTest {
CliBaseOptions(noCache = true),
listOf(tempDir),
consoleWriter = StringWriter(),
errWriter = StringWriter(),
errWriter = StringWriter()
)
val err = assertThrows<CliException> { packager.run() }
assertThat(err).hasMessageStartingWith("Directory $tempDir does not contain a PklProject file.")
@@ -79,18 +79,18 @@ class CliProjectResolverTest {
}
}
"""
.trimIndent(),
.trimIndent()
)
CliProjectResolver(
CliBaseOptions(
workingDir = tempDir,
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = packageServer.port,
noCache = true,
noCache = true
),
listOf(tempDir),
consoleWriter = StringWriter(),
errWriter = StringWriter(),
errWriter = StringWriter()
)
.run()
val expectedOutput = tempDir.resolve("PklProject.deps.json")
@@ -134,18 +134,18 @@ class CliProjectResolverTest {
}
}
"""
.trimIndent(),
.trimIndent()
)
CliProjectResolver(
CliBaseOptions(
workingDir = tempDir,
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = packageServer.port,
noCache = true,
noCache = true
),
emptyList(),
consoleWriter = StringWriter(),
errWriter = StringWriter(),
errWriter = StringWriter()
)
.run()
val expectedOutput = tempDir.resolve("PklProject.deps.json")
@@ -191,7 +191,7 @@ class CliProjectResolverTest {
["project2"] = import("../project2/PklProject")
}
"""
.trimIndent(),
.trimIndent()
)
projectDir.writeFile(
"../project2/PklProject",
@@ -212,7 +212,7 @@ class CliProjectResolverTest {
["project3"] = import("../project3/PklProject")
}
"""
.trimIndent(),
.trimIndent()
)
projectDir.writeFile(
@@ -233,17 +233,17 @@ class CliProjectResolverTest {
}
}
"""
.trimIndent(),
.trimIndent()
)
CliProjectResolver(
CliBaseOptions(
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = packageServer.port,
noCache = true,
noCache = true
),
listOf(projectDir),
consoleWriter = StringWriter(),
errWriter = StringWriter(),
errWriter = StringWriter()
)
.run()
val expectedOutput = projectDir.resolve("PklProject.deps.json")
@@ -299,7 +299,7 @@ class CliProjectResolverTest {
["fruit"] = import("../fruit/PklProject")
}
"""
.trimIndent(),
.trimIndent()
)
projectDir.writeFile(
"../fruit/PklProject",
@@ -313,7 +313,7 @@ class CliProjectResolverTest {
packageZipUrl = "https://foo.com/fruit.zip"
}
"""
.trimIndent(),
.trimIndent()
)
val consoleOut = StringWriter()
val errOut = StringWriter()
@@ -321,11 +321,11 @@ class CliProjectResolverTest {
CliBaseOptions(
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = packageServer.port,
noCache = true,
noCache = true
),
listOf(projectDir),
consoleWriter = consoleOut,
errWriter = errOut,
errWriter = errOut
)
.run()
val expectedOutput = projectDir.resolve("PklProject.deps.json")
@@ -373,7 +373,7 @@ class CliProjectResolverTest {
}
}
"""
.trimIndent(),
.trimIndent()
)
tempDir.writeFile(
@@ -387,7 +387,7 @@ class CliProjectResolverTest {
}
}
"""
.trimIndent(),
.trimIndent()
)
val consoleOut = StringWriter()
@@ -396,11 +396,11 @@ class CliProjectResolverTest {
CliBaseOptions(
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = packageServer.port,
noCache = true,
noCache = true
),
listOf(tempDir.resolve("project1"), tempDir.resolve("project2")),
consoleWriter = consoleOut,
errWriter = errOut,
errWriter = errOut
)
.run()
val sep = File.separatorChar

View File

@@ -15,17 +15,19 @@
*/
package org.pkl.cli
import com.github.ajalt.clikt.testing.test
import com.github.ajalt.clikt.core.MissingArgument
import com.github.ajalt.clikt.core.subcommands
import java.io.StringWriter
import java.io.Writer
import java.net.URI
import java.nio.file.Path
import java.util.*
import java.util.Locale
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatCode
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.io.TempDir
import org.pkl.cli.commands.EvalCommand
import org.pkl.cli.commands.RootCommand
import org.pkl.commons.cli.CliBaseOptions
import org.pkl.commons.cli.CliException
@@ -33,6 +35,7 @@ import org.pkl.commons.cli.CliTestOptions
import org.pkl.commons.readString
import org.pkl.commons.toUri
import org.pkl.commons.writeString
import org.pkl.core.Release
class CliTestRunnerTest {
@Test
@@ -378,7 +381,7 @@ class CliTestRunnerTest {
val opts =
CliBaseOptions(
sourceModules = listOf(input.toUri(), input2.toUri()),
settings = URI("pkl:settings"),
settings = URI("pkl:settings")
)
val testOpts = CliTestOptions(junitDir = tempDir)
val runner = CliTestRunner(opts, testOpts, noopWriter, noopWriter)
@@ -388,9 +391,14 @@ class CliTestRunnerTest {
@Test
fun `no source modules specified has same message as pkl eval`() {
val e1 = assertThrows<CliException> { CliTestRunner(CliBaseOptions(), CliTestOptions()).run() }
val e2 = RootCommand().test("eval")
assertThat(e1).hasMessageContaining("missing argument <modules>")
assertThat(e1.message!!.replace("test", "eval") + "\n").isEqualTo(e2.stderr)
val e2 =
assertThrows<MissingArgument> {
val rootCommand =
RootCommand("pkl", Release.current().versionInfo(), "").subcommands(EvalCommand(""))
rootCommand.parse(listOf("eval"))
}
assertThat(e1).hasMessageContaining("Missing argument \"<modules>\"")
assertThat(e1.message!!.replace("test", "eval")).isEqualTo(e2.helpMessage())
}
@Test

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@ package org.pkl.cli
import java.nio.charset.StandardCharsets
import java.nio.file.Path
import kotlin.io.path.createParentDirectories
import org.pkl.commons.createParentDirectories
import org.pkl.commons.writeString
fun Path.writeFile(fileName: String, contents: String): Path {

View File

@@ -1,78 +1,40 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
com.github.ajalt.clikt:clikt-core-jvm:5.0.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ajalt.clikt:clikt-core:5.0.3=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.ajalt.clikt:clikt-jvm:5.0.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ajalt.clikt:clikt-markdown-jvm:5.0.3=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.clikt:clikt-markdown:5.0.3=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.clikt:clikt:5.0.3=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.ajalt.colormath:colormath-jvm:3.6.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ajalt.colormath:colormath:3.6.0=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.ajalt.mordant:mordant-core-jvm:3.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-core:3.0.1=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm-ffm-jvm:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm-ffm:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm-graal-ffi-jvm:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm-graal-ffi:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm-jna-jvm:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm-jna:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-jvm:3.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-markdown-jvm:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant-markdown:3.0.1=runtimeClasspath,testRuntimeClasspath
com.github.ajalt.mordant:mordant:3.0.1=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.palantir.javapoet:javapoet:0.6.0=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.github.ajalt.clikt:clikt-jvm:3.5.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ajalt.clikt:clikt:3.5.4=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.squareup:javapoet:1.13.0=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
com.tunnelvisionlabs:antlr4-runtime:4.9.0=runtimeClasspath,testRuntimeClasspath
io.leangen.geantyref:geantyref:1.3.16=testRuntimeClasspath
net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
net.java.dev.jna:jna:5.14.0=runtimeClasspath,testRuntimeClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.27.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.polyglot:polyglot:24.1.2=runtimeClasspath,testRuntimeClasspath
org.graalvm.sdk:collections:24.1.2=runtimeClasspath,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:24.1.2=runtimeClasspath,testRuntimeClasspath
org.graalvm.sdk:nativeimage:24.1.2=runtimeClasspath,testRuntimeClasspath
org.graalvm.sdk:word:24.1.2=runtimeClasspath,testRuntimeClasspath
org.graalvm.truffle:truffle-api:24.1.2=runtimeClasspath,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-build-tools-impl:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-compiler-runner:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-daemon-client:2.0.21=kotlinBuildToolsApiClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:2.0.21=kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-native-prebuilt:2.0.21=kotlinNativeBundleConfiguration
org.jetbrains.kotlin:kotlin-reflect:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-script-runtime:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-scripting-common:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17
org.jetbrains.kotlin:kotlin-scripting-jvm:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17
org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.0.21=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.0.21=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:2.0.21=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains:annotations:13.0=compileClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains:markdown-jvm:0.7.3=runtimeClasspath,testRuntimeClasspath
org.jetbrains:markdown:0.7.3=runtimeClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-api:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-engine:5.8.2=testJdk17RuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.jupiter:junit-jupiter:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.platform:junit-platform-commons:1.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.platform:junit-platform-commons:1.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.junit.platform:junit-platform-engine:1.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.platform:junit-platform-engine:1.8.2=testJdk17RuntimeClasspath
org.junit.platform:junit-platform-launcher:1.8.2=testJdk17RuntimeClasspath
org.junit:junit-bom:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit:junit-bom:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
net.bytebuddy:byte-buddy:1.14.18=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:23.0.6=runtimeClasspath,testRuntimeClasspath
org.graalvm.truffle:truffle-api:23.0.6=runtimeClasspath,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.7.10=kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-reflect:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-script-runtime:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-scripting-common:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-scripting-jvm:1.7.10=kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:1.7.10=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains:annotations:13.0=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-engine:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.jupiter:junit-jupiter-params:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit.platform:junit-platform-engine:1.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.junit:junit-bom:5.11.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.msgpack:msgpack-core:0.9.8=runtimeClasspath,testRuntimeClasspath
org.opentest4j:opentest4j:1.2.0=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
org.organicdesign:Paguro:3.10.3=runtimeClasspath,testRuntimeClasspath
org.snakeyaml:snakeyaml-engine:2.9=runtimeClasspath,testRuntimeClasspath
empty=annotationProcessor,compileOnlyDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtimeOnlyDependenciesMetadata,signatures,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testJdk17AnnotationProcessor,testJdk17ApiDependenciesMetadata,testJdk17CompileOnlyDependenciesMetadata,testJdk17IntransitiveDependenciesMetadata,testJdk17KotlinScriptDefExtensions,testKotlinScriptDef,testKotlinScriptDefExtensions
org.snakeyaml:snakeyaml-engine:2.5=runtimeClasspath,testRuntimeClasspath
empty=annotationProcessor,compileOnlyDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtimeOnlyDependenciesMetadata,signatures,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,9 @@
package org.pkl.codegen.java
import java.io.IOException
import kotlin.io.path.createParentDirectories
import org.pkl.commons.cli.CliCommand
import org.pkl.commons.cli.CliException
import org.pkl.commons.createParentDirectories
import org.pkl.commons.writeString
import org.pkl.core.Closeables
import org.pkl.core.ModuleSource
@@ -33,7 +33,7 @@ class CliJavaCodeGenerator(private val options: CliJavaCodeGeneratorOptions) :
builder.build().use { evaluator ->
for (moduleUri in options.base.normalizedSourceModules) {
val schema = evaluator.evaluateSchema(ModuleSource.uri(moduleUri))
val codeGenerator = JavaCodeGenerator(schema, options.toJavaCodeGeneratorOptions())
val codeGenerator = JavaCodeGenerator(schema, options.toJavaCodegenOptions())
try {
for ((fileName, fileContents) in codeGenerator.output) {
val outputFile = options.outputDir.resolve(fileName)

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,35 +35,25 @@ data class CliJavaCodeGeneratorOptions(
*/
val generateGetters: Boolean = false,
/** Whether to preserve Pkl doc comments by generating corresponding Javadoc comments. */
/** Whether to generate Javadoc based on doc comments for Pkl modules, classes, and properties. */
val generateJavadoc: Boolean = false,
/** Whether to generate config classes for use with Spring Boot. */
val generateSpringBootConfig: Boolean = false,
/**
* Fully qualified name of the annotation type to use for annotating constructor parameters with
* their name.
*
* The specified annotation type must have a `value` parameter of type [java.lang.String] or the
* generated code may not compile.
*
* If set to `null`, constructor parameters are not annotated. The default value is `null` if
* [generateSpringBootConfig] is `true` and `"org.pkl.config.java.mapper.Named"` otherwise.
* Fully qualified name of the annotation to use on constructor parameters. If this options is not
* set, [org.pkl.config.java.mapper.Named] will be used.
*/
val paramsAnnotation: String? =
if (generateSpringBootConfig) null else "org.pkl.config.java.mapper.Named",
val paramsAnnotation: String? = null,
/**
* Fully qualified name of the annotation type to use for annotating non-null types.
*
* The specified annotation type must have a [java.lang.annotation.Target] of
* [java.lang.annotation.ElementType.TYPE_USE] or the generated code may not compile. If set to
* `null`, [org.pkl.config.java.mapper.NonNull] will be used.
* Fully qualified name of the annotation to use on non-null properties. If this option is not
* set, [org.pkl.config.java.mapper.NonNull] will be used.
*/
val nonNullAnnotation: String? = null,
/** Whether to generate classes that implement [java.io.Serializable]. */
/** Whether to make generated classes implement [java.io.Serializable] */
val implementSerializable: Boolean = false,
/**
@@ -73,14 +63,10 @@ data class CliJavaCodeGeneratorOptions(
* Pkl module names, you can define a rename mapping, where the key is a prefix of the original
* Pkl module name, and the value is the desired replacement.
*/
val renames: Map<String, String> = emptyMap(),
val renames: Map<String, String> = emptyMap()
) {
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("deprecated without replacement")
fun toJavaCodegenOptions() = toJavaCodeGeneratorOptions()
internal fun toJavaCodeGeneratorOptions() =
JavaCodeGeneratorOptions(
fun toJavaCodegenOptions() =
JavaCodegenOptions(
indent,
generateGetters,
generateJavadoc,
@@ -88,6 +74,6 @@ data class CliJavaCodeGeneratorOptions(
paramsAnnotation,
nonNullAnnotation,
implementSerializable,
renames,
renames
)
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,9 +15,10 @@
*/
package org.pkl.codegen.java
import com.palantir.javapoet.*
import com.squareup.javapoet.*
import java.io.StringWriter
import java.lang.Deprecated
import java.net.URI
import java.util.*
import java.util.regex.Pattern
import javax.lang.model.element.Modifier
@@ -40,10 +41,7 @@ import org.pkl.core.util.IoUtils
class JavaCodeGeneratorException(message: String) : RuntimeException(message)
@kotlin.Deprecated("renamed to JavaCodeGeneratorOptions", ReplaceWith("JavaCodeGeneratorOptions"))
typealias JavaCodegenOptions = JavaCodeGeneratorOptions
data class JavaCodeGeneratorOptions(
data class JavaCodegenOptions(
/** The characters to use for indenting generated Java code. */
val indent: String = " ",
@@ -53,35 +51,25 @@ data class JavaCodeGeneratorOptions(
*/
val generateGetters: Boolean = false,
/** Whether to preserve Pkl doc comments by generating corresponding Javadoc comments. */
/** Whether to generate Javadoc based on doc comments for Pkl modules, classes, and properties. */
val generateJavadoc: Boolean = false,
/** Whether to generate config classes for use with Spring Boot. */
val generateSpringBootConfig: Boolean = false,
/**
* Fully qualified name of the annotation type to use for annotating constructor parameters with
* their name.
*
* The specified annotation type must have a `value` parameter of type [java.lang.String] or the
* generated code may not compile.
*
* If set to `null`, constructor parameters are not annotated. The default value is `null` if
* [generateSpringBootConfig] is `true` and `"org.pkl.config.java.mapper.Named"` otherwise.
* Fully qualified name of the annotation to use on constructor parameters. If this options is not
* set, [org.pkl.config.java.mapper.Named] will be used.
*/
val paramsAnnotation: String? =
if (generateSpringBootConfig) null else "org.pkl.config.java.mapper.Named",
val paramsAnnotation: String? = null,
/**
* Fully qualified name of the annotation type to use for annotating non-null types.
*
* The specified annotation type must have a [java.lang.annotation.Target] of
* [java.lang.annotation.ElementType.TYPE_USE] or the generated code may not compile. If set to
* `null`, [org.pkl.config.java.mapper.NonNull] will be used.
* Fully qualified name of the annotation to use on non-null properties. If this option is not
* set, [org.pkl.config.java.mapper.NonNull] will be used.
*/
val nonNullAnnotation: String? = null,
/** Whether to generate classes that implement [java.io.Serializable]. */
/** Whether to make generated classes implement [java.io.Serializable] */
val implementSerializable: Boolean = false,
/**
@@ -90,17 +78,16 @@ data class JavaCodeGeneratorOptions(
* Can be used when the class or package name in the generated source code should be different
* from the corresponding name derived from the Pkl module declaration .
*/
val renames: Map<String, String> = emptyMap(),
val renames: Map<String, String> = emptyMap()
)
/** Entrypoint for the Java code generator API. */
class JavaCodeGenerator(
private val schema: ModuleSchema,
private val codegenOptions: JavaCodeGeneratorOptions,
private val codegenOptions: JavaCodegenOptions
) {
companion object {
private val OBJECT = ClassName.get(Object::class.java)
private val STRING = ClassName.get(String::class.java)
private val DURATION = ClassName.get(Duration::class.java)
private val DURATION_UNIT = ClassName.get(DurationUnit::class.java)
@@ -114,7 +101,7 @@ class JavaCodeGenerator(
private val PMODULE = ClassName.get(PModule::class.java)
private val PCLASS = ClassName.get(PClass::class.java)
private val PATTERN = ClassName.get(Pattern::class.java)
private val URI = ClassName.get(java.net.URI::class.java)
private val URI = ClassName.get(URI::class.java)
private val VERSION = ClassName.get(Version::class.java)
private const val PROPERTY_PREFIX: String = "org.pkl.config.java.mapper."
@@ -234,23 +221,20 @@ class JavaCodeGenerator(
val properties = renameIfReservedWord(pClass.properties).filterValues { !it.isHidden }
val allProperties = superProperties + properties
fun PClass.Property.isRegex(): Boolean =
(this.type as? PType.Class)?.pClass?.info == PClassInfo.Regex
fun addCtorParameter(
builder: MethodSpec.Builder,
propJavaName: String,
property: PClass.Property,
property: PClass.Property
) {
val paramBuilder = ParameterSpec.builder(property.type.toJavaPoetName(), propJavaName)
if (paramsAnnotationName != null) {
paramBuilder.addAnnotation(
AnnotationSpec.builder(paramsAnnotationName)
.addMember("value", "\$S", property.simpleName)
.build()
)
}
builder.addParameter(paramBuilder.build())
builder.addParameter(
ParameterSpec.builder(property.type.toJavaPoetName(), propJavaName)
.addAnnotation(
AnnotationSpec.builder(namedAnnotationName)
.addMember("value", "\$S", property.simpleName)
.build()
)
.build()
)
}
fun generateConstructor(isInstantiable: Boolean): MethodSpec {
@@ -299,12 +283,14 @@ class JavaCodeGenerator(
.addStatement("\$T other = (\$T) obj", javaPoetClassName, javaPoetClassName)
for ((propertyName, property) in allProperties) {
val accessor = if (property.isRegex()) "\$N.pattern()" else "\$N"
val accessor =
if ((property.type as? PType.Class)?.pClass?.info == PClassInfo.Regex) "\$N.pattern()"
else "\$N"
builder.addStatement(
"if (!\$T.equals(this.$accessor, other.$accessor)) return false",
Objects::class.java,
propertyName,
propertyName,
propertyName
)
}
@@ -320,12 +306,11 @@ class JavaCodeGenerator(
.returns(Int::class.java)
.addStatement("int result = 1")
for ((propertyName, property) in allProperties) {
val accessor = if (property.isRegex()) "this.\$N.pattern()" else "this.\$N"
for (propertyName in allProperties.keys) {
builder.addStatement(
"result = 31 * result + \$T.hashCode($accessor)",
"result = 31 * result + \$T.hashCode(this.\$N)",
Objects::class.java,
propertyName,
propertyName
)
}
@@ -347,7 +332,7 @@ class JavaCodeGenerator(
appendBuilder.addStatement(
"appendProperty(builder, \$S, this.\$N)",
propertyName,
propertyName,
propertyName
)
}
@@ -356,7 +341,7 @@ class JavaCodeGenerator(
"\$T builder = new \$T(\$L)",
StringBuilder::class.java,
StringBuilder::class.java,
builderSize,
builderSize
)
.addStatement("builder.append(\$T.class.getSimpleName()).append(\" {\")", javaPoetClassName)
.addCode(appendBuilder.build())
@@ -380,7 +365,7 @@ class JavaCodeGenerator(
annotations: Collection<PObject>,
hasJavadoc: Boolean,
addAnnotation: (Class<*>) -> Unit,
addJavadoc: (String) -> Unit,
addJavadoc: (String) -> Unit
) {
annotations
.firstOrNull { it.classInfo == PClassInfo.Deprecated }
@@ -416,7 +401,7 @@ class JavaCodeGenerator(
property.annotations,
hasJavadoc,
{ builder.addAnnotation(it) },
{ builder.addJavadoc(it) },
{ builder.addJavadoc(it) }
)
builder.addModifiers(Modifier.PUBLIC)
}
@@ -429,7 +414,7 @@ class JavaCodeGenerator(
fun generateGetter(
propertyName: String,
property: PClass.Property,
isOverridden: Boolean,
isOverridden: Boolean
): MethodSpec {
val propertyType = property.type
val isBooleanProperty =
@@ -459,7 +444,7 @@ class JavaCodeGenerator(
property.annotations,
hasJavadoc,
{ builder.addAnnotation(it) },
{ builder.addJavadoc(it) },
{ builder.addJavadoc(it) }
)
return builder.build()
@@ -478,7 +463,7 @@ class JavaCodeGenerator(
property.annotations,
false,
{ methodBuilder.addAnnotation(it) },
{ methodBuilder.addJavadoc(it) },
{ methodBuilder.addJavadoc(it) }
)
val codeBuilder = CodeBlock.builder()
@@ -534,7 +519,7 @@ class JavaCodeGenerator(
AnnotationSpec.builder(
ClassName.get(
"org.springframework.boot.context.properties",
"ConfigurationProperties",
"ConfigurationProperties"
)
)
// use "value" instead of "prefix" to entice JavaPoet to generate a single-line
@@ -571,7 +556,7 @@ class JavaCodeGenerator(
pClass.annotations,
hasJavadoc,
{ builder.addAnnotation(it) },
{ builder.addJavadoc(it) },
{ builder.addJavadoc(it) }
)
if (!isModuleClass) {
@@ -631,7 +616,7 @@ class JavaCodeGenerator(
private fun generateEnumTypeSpec(
typeAlias: TypeAlias,
stringLiterals: Set<String>,
stringLiterals: Set<String>
): TypeSpec.Builder {
val enumConstantToPklNames =
stringLiterals
@@ -673,15 +658,19 @@ class JavaCodeGenerator(
for ((enumConstantName, pklName) in enumConstantToPklNames) {
builder.addEnumConstant(
enumConstantName,
TypeSpec.anonymousClassBuilder("\$S", pklName).build(),
TypeSpec.anonymousClassBuilder("\$S", pklName).build()
)
}
return builder
}
private val paramsAnnotationName: ClassName? =
codegenOptions.paramsAnnotation?.let { toClassName(it) }
private val namedAnnotationName =
if (codegenOptions.paramsAnnotation != null) {
toClassName(codegenOptions.paramsAnnotation)
} else {
ClassName.get("org.pkl.config.java.mapper", "Named")
}
private fun appendPropertyMethod() =
MethodSpec.methodBuilder("appendProperty")
@@ -693,7 +682,7 @@ class JavaCodeGenerator(
.addStatement(
"\$T lines = \$T.toString(value).split(\"\\n\")",
ArrayTypeName.of(String::class.java),
Objects::class.java,
Objects::class.java
)
.addStatement("builder.append(lines[0])")
.beginControlFlow("for (int i = 1; i < lines.length; i++)")
@@ -717,7 +706,7 @@ class JavaCodeGenerator(
/** Generate `List<? extends Foo>` if `Foo` is `abstract` or `open`, to allow subclassing. */
private fun PType.toJavaPoetTypeArgumentName(): TypeName {
val baseName = toJavaPoetName(boxed = true)
val baseName = toJavaPoetName(nullable = false, boxed = true)
return if (this is PType.Class && (pClass.isAbstract || pClass.isOpen)) {
WildcardTypeName.subtypeOf(baseName)
} else {
@@ -727,15 +716,15 @@ class JavaCodeGenerator(
private fun PType.toJavaPoetName(nullable: Boolean = false, boxed: Boolean = false): TypeName =
when (this) {
PType.UNKNOWN -> OBJECT.nullableIf(nullable)
PType.UNKNOWN -> TypeName.OBJECT.nullableIf(nullable)
PType.NOTHING -> TypeName.VOID
is PType.StringLiteral -> STRING.nullableIf(nullable)
is PType.Class -> {
// if in doubt, spell it out
when (val classInfo = pClass.info) {
PClassInfo.Any -> OBJECT
PClassInfo.Any -> TypeName.OBJECT
PClassInfo.Typed,
PClassInfo.Dynamic -> OBJECT.nullableIf(nullable)
PClassInfo.Dynamic -> TypeName.OBJECT.nullableIf(nullable)
PClassInfo.Boolean -> TypeName.BOOLEAN.boxIf(boxed).nullableIf(nullable)
PClassInfo.String -> STRING.nullableIf(nullable)
// seems more useful to generate `double` than `java.lang.Number`
@@ -748,25 +737,25 @@ class JavaCodeGenerator(
ParameterizedTypeName.get(
PAIR,
if (typeArguments.isEmpty()) {
OBJECT
TypeName.OBJECT
} else {
typeArguments[0].toJavaPoetTypeArgumentName()
},
if (typeArguments.isEmpty()) {
OBJECT
TypeName.OBJECT
} else {
typeArguments[1].toJavaPoetTypeArgumentName()
},
}
)
.nullableIf(nullable)
PClassInfo.Collection ->
ParameterizedTypeName.get(
COLLECTION,
if (typeArguments.isEmpty()) {
OBJECT
TypeName.OBJECT
} else {
typeArguments[0].toJavaPoetTypeArgumentName()
},
}
)
.nullableIf(nullable)
PClassInfo.List,
@@ -774,10 +763,10 @@ class JavaCodeGenerator(
ParameterizedTypeName.get(
LIST,
if (typeArguments.isEmpty()) {
OBJECT
TypeName.OBJECT
} else {
typeArguments[0].toJavaPoetTypeArgumentName()
},
}
)
.nullableIf(nullable)
}
@@ -785,10 +774,10 @@ class JavaCodeGenerator(
ParameterizedTypeName.get(
SET,
if (typeArguments.isEmpty()) {
OBJECT
TypeName.OBJECT
} else {
typeArguments[0].toJavaPoetTypeArgumentName()
},
}
)
.nullableIf(nullable)
PClassInfo.Map,
@@ -796,15 +785,15 @@ class JavaCodeGenerator(
ParameterizedTypeName.get(
MAP,
if (typeArguments.isEmpty()) {
OBJECT
TypeName.OBJECT
} else {
typeArguments[0].toJavaPoetTypeArgumentName()
},
if (typeArguments.isEmpty()) {
OBJECT
TypeName.OBJECT
} else {
typeArguments[1].toJavaPoetTypeArgumentName()
},
}
)
.nullableIf(nullable)
PClassInfo.Module -> PMODULE.nullableIf(nullable)
@@ -826,7 +815,7 @@ class JavaCodeGenerator(
is PType.Constrained -> baseType.toJavaPoetName(nullable = nullable, boxed = boxed)
is PType.Alias ->
when (typeAlias.qualifiedName) {
"pkl.base#NonNull" -> OBJECT.nullableIf(nullable)
"pkl.base#NonNull" -> TypeName.OBJECT.nullableIf(nullable)
"pkl.base#Int8" -> TypeName.BYTE.boxIf(boxed).nullableIf(nullable)
"pkl.base#Int16",
"pkl.base#UInt8" -> TypeName.SHORT.boxIf(boxed).nullableIf(nullable)
@@ -941,5 +930,5 @@ internal val javaReservedWords =
"try",
"void",
"volatile",
"while",
"while"
)

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,14 +17,15 @@
package org.pkl.codegen.java
import com.github.ajalt.clikt.core.main
import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.options.associate
import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.types.path
import java.nio.file.Path
import org.pkl.commons.cli.CliBaseOptions
import org.pkl.commons.cli.cliMain
import org.pkl.commons.cli.commands.ModulesCommand
import org.pkl.commons.cli.commands.installCommonOptions
import org.pkl.commons.toPath
import org.pkl.core.Release
@@ -33,16 +34,19 @@ internal fun main(args: Array<String>) {
cliMain { PklJavaCodegenCommand().main(args) }
}
internal val helpLink = "${Release.current().documentation.homepage}java-binding/codegen.html#cli"
class PklJavaCodegenCommand :
ModulesCommand(
name = "pkl-codegen-java",
helpLink = Release.current().documentation().homepage(),
) {
class PklJavaCodegenCommand : ModulesCommand(name = "pkl-codegen-java", helpLink) {
private val defaults = CliJavaCodeGeneratorOptions(CliBaseOptions(), "".toPath())
private val outputDir: Path by
option(
names = arrayOf("-o", "--output-dir"),
metavar = "path",
help = "The directory where generated source code is placed.",
metavar = "<path>",
help = "The directory where generated source code is placed."
)
.path()
.default(defaults.outputDir)
@@ -50,8 +54,8 @@ class PklJavaCodegenCommand : ModulesCommand(name = "pkl-codegen-java", helpLink
private val indent: String by
option(
names = arrayOf("--indent"),
metavar = "chars",
help = "The characters to use for indenting generated source code.",
metavar = "<chars>",
help = "The characters to use for indenting generated source code."
)
.default(defaults.indent)
@@ -60,72 +64,66 @@ class PklJavaCodegenCommand : ModulesCommand(name = "pkl-codegen-java", helpLink
names = arrayOf("--generate-getters"),
help =
"Whether to generate public getter methods and " +
"private final fields instead of public final fields.",
"private final fields instead of public final fields."
)
.flag()
private val generateJavadoc: Boolean by
option(
names = arrayOf("--generate-javadoc"),
help = "Whether to preserve Pkl doc comments by generating corresponding Javadoc comments.",
help =
"Whether to generate Javadoc based on doc comments " +
"for Pkl modules, classes, and properties."
)
.flag()
private val generateSpringBoot: Boolean by
private val generateSpringboot: Boolean by
option(
names = arrayOf("--generate-spring-boot"),
help = "Whether to generate config classes for use with Spring Boot.",
help = "Whether to generate config classes for use with Spring boot."
)
.flag()
private val paramsAnnotation: String by
private val paramsAnnotation: String? by
option(
names = arrayOf("--params-annotation"),
help =
"Fully qualified name of the annotation type to use for annotating constructor parameters with their name.",
)
.defaultLazy(
"`none` if `--generate-spring-boot` is set, `org.pkl.config.java.mapper.Named` otherwise"
) {
if (generateSpringBoot) "none" else "org.pkl.config.java.mapper.Named"
}
names = arrayOf("--params-annotation"),
help = "Fully qualified name of the annotation to use on constructor parameters."
)
private val nonNullAnnotation: String? by
option(
names = arrayOf("--non-null-annotation"),
help =
"""
Fully qualified name of the annotation type to use for annotating non-null types.
The specified annotation type must be annotated with `@java.lang.annotation.Target(ElementType.TYPE_USE)`
or the generated code may not compile.
Fully qualified named of the annotation class to use for non-null types.
This annotation is required to have `java.lang.annotation.ElementType.TYPE_USE` as a `@Target`
or it may generate code that does not compile.
"""
.trimIndent(),
.trimIndent()
)
private val implementSerializable: Boolean by
option(
names = arrayOf("--implement-serializable"),
help = "Whether to generate classes that implement java.io.Serializable.",
help = "Whether to make generated classes implement java.io.Serializable."
)
.flag()
private val renames: Map<String, String> by
option(
names = arrayOf("--rename"),
metavar = "old_name=new_name",
metavar = "<old_name=new_name>",
help =
"""
Replace a prefix in the names of the generated Java classes (repeatable).
By default, the names of generated classes are derived from the Pkl module names.
With this option, you can override or modify the default names, renaming entire
With this option, you can override the modify the default names, renaming entire
classes or just their packages.
"""
.trimIndent(),
.trimIndent()
)
.associate()
override val helpString: String = "Generate Java classes and interfaces from Pkl module(s)"
override fun run() {
val options =
CliJavaCodeGeneratorOptions(
@@ -134,16 +132,12 @@ class PklJavaCodegenCommand : ModulesCommand(name = "pkl-codegen-java", helpLink
indent = indent,
generateGetters = generateGetters,
generateJavadoc = generateJavadoc,
generateSpringBootConfig = generateSpringBoot,
paramsAnnotation = if (paramsAnnotation == "none") null else paramsAnnotation,
generateSpringBootConfig = generateSpringboot,
paramsAnnotation = paramsAnnotation,
nonNullAnnotation = nonNullAnnotation,
implementSerializable = implementSerializable,
renames = renames,
renames = renames
)
CliJavaCodeGenerator(options).run()
}
init {
installCommonOptions()
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ class CliJavaCodeGeneratorTest {
name: String
age: Int
}
""",
"""
)
val module2 =
@@ -53,7 +53,7 @@ class CliJavaCodeGeneratorTest {
extends "mod1.pkl"
parrot: Person
""",
"""
)
val module1File = module1.writeToDisk(tempDir.resolve("org/mod1.pkl"))
@@ -64,7 +64,7 @@ class CliJavaCodeGeneratorTest {
CliJavaCodeGenerator(
CliJavaCodeGeneratorOptions(
CliBaseOptions(listOf(module1File.toUri(), module2File.toUri())),
outputDir,
outputDir
)
)
@@ -82,7 +82,7 @@ class CliJavaCodeGeneratorTest {
|public class Mod1 {
| public final @NonNull Person pigeon;
""",
module1JavaFile.readString(),
module1JavaFile.readString()
)
val module2JavaFile = javaDir.resolve("org/Mod2.java")
@@ -91,7 +91,7 @@ class CliJavaCodeGeneratorTest {
|public final class Mod2 extends Mod1 {
| public final Mod1. @NonNull Person parrot;
""",
module2JavaFile.readString(),
module2JavaFile.readString()
)
val resourcesDir = outputDir.resolve("resources/META-INF/org/pkl/config/java/mapper/classes/")
@@ -101,18 +101,18 @@ class CliJavaCodeGeneratorTest {
// use two assertions because java.util.Properties doesn't guarantee order
assertContains(
"""org.pkl.config.java.mapper.org.mod1\#Person=org.Mod1${dollar}Person""",
module1PropertiesString,
module1PropertiesString
)
assertContains(
"""org.pkl.config.java.mapper.org.mod1\#ModuleClass=org.Mod1""",
module1PropertiesString,
module1PropertiesString
)
val module2PropertiesFile = resourcesDir.resolve("org.mod2.properties")
assertContains(
"""org.pkl.config.java.mapper.org.mod2\#ModuleClass=org.Mod2""",
module2PropertiesFile.readString(),
module2PropertiesFile.readString()
)
}
@@ -127,7 +127,7 @@ class CliJavaCodeGeneratorTest {
class Person {
name: String
}
""",
"""
)
val module2 =
@@ -144,7 +144,7 @@ class CliJavaCodeGeneratorTest {
class Person {
age: Int
}
""",
"""
)
val module1PklFile = module1.writeToDisk(tempDir.resolve("org/mod1.pkl"))
@@ -155,7 +155,7 @@ class CliJavaCodeGeneratorTest {
CliJavaCodeGenerator(
CliJavaCodeGeneratorOptions(
CliBaseOptions(listOf(module1PklFile.toUri(), module2PklFile.toUri())),
outputDir,
outputDir
)
)
@@ -169,7 +169,7 @@ class CliJavaCodeGeneratorTest {
|
| public final @NonNull Person person2;
""",
module2JavaFile.readString(),
module2JavaFile.readString()
)
}
@@ -184,7 +184,7 @@ class CliJavaCodeGeneratorTest {
class Person {
name: String
}
""",
"""
)
val module2 =
@@ -199,7 +199,7 @@ class CliJavaCodeGeneratorTest {
owner: Module1.Person
name: String
}
""",
"""
)
val module3 =
@@ -213,7 +213,7 @@ class CliJavaCodeGeneratorTest {
class Supergroup {
owner: Module2.Group
}
""",
"""
)
val module1PklFile = module1.writeToDisk(tempDir.resolve("org/foo/Module1.pkl"))
@@ -226,7 +226,7 @@ class CliJavaCodeGeneratorTest {
CliJavaCodeGeneratorOptions(
CliBaseOptions(listOf(module1PklFile, module2PklFile, module3PklFile).map { it.toUri() }),
outputDir,
renames = mapOf("org.foo" to "com.foo.x", "org.baz" to "com.baz.a.b"),
renames = mapOf("org.foo" to "com.foo.x", "org.baz" to "com.baz.a.b")
)
)
@@ -243,7 +243,7 @@ class CliJavaCodeGeneratorTest {
| public static final class Person {
| public final @NonNull String name;
""",
it,
it
)
}
@@ -260,7 +260,7 @@ class CliJavaCodeGeneratorTest {
| public static final class Group {
| public final Module1. @NonNull Person owner;
""",
it,
it
)
}
@@ -277,7 +277,7 @@ class CliJavaCodeGeneratorTest {
| public static final class Supergroup {
| public final Module2. @NonNull Group owner;
""",
it,
it
)
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -87,7 +87,7 @@ private class InMemoryFileManager(delegate: JavaFileManager) :
location: JavaFileManager.Location,
className: String,
kind: JavaFileObject.Kind,
sibling: FileObject,
sibling: FileObject
): JavaFileObject {
return WritableBinaryFileObject(className, kind).also { outputFiles[className] = it }

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -104,10 +104,26 @@ class JavaCodeGeneratorTest {
private fun generateJavaCode(
pklCode: String,
options: JavaCodeGeneratorOptions = JavaCodeGeneratorOptions(),
generateGetters: Boolean = false,
generateJavadoc: Boolean = false,
generateSpringBootConfig: Boolean = false,
nonNullAnnotation: String? = null,
implementSerializable: Boolean = false,
renames: Map<String, String> = emptyMap()
): JavaSourceCode {
val module = Evaluator.preconfigured().evaluateSchema(text(pklCode))
val generator = JavaCodeGenerator(module, options)
val generator =
JavaCodeGenerator(
module,
JavaCodegenOptions(
generateGetters = generateGetters,
generateJavadoc = generateJavadoc,
generateSpringBootConfig = generateSpringBootConfig,
nonNullAnnotation = nonNullAnnotation,
implementSerializable = implementSerializable,
renames = renames
)
)
return JavaSourceCode(generator.javaFile)
}
}
@@ -219,7 +235,7 @@ class JavaCodeGeneratorTest {
}
"""
.trimIndent(),
JavaCodeGeneratorOptions(generateJavadoc = true),
generateJavadoc = true
)
assertThat(javaCode)
.contains(
@@ -258,7 +274,8 @@ class JavaCodeGeneratorTest {
}
"""
.trimIndent(),
JavaCodeGeneratorOptions(generateGetters = true, generateJavadoc = true),
generateGetters = true,
generateJavadoc = true
)
assertThat(javaCode)
.contains(
@@ -305,7 +322,7 @@ class JavaCodeGeneratorTest {
}
"""
.trimIndent(),
JavaCodeGeneratorOptions(generateJavadoc = true),
generateJavadoc = true
)
assertThat(javaCode)
.contains(
@@ -332,7 +349,7 @@ class JavaCodeGeneratorTest {
propertyInDeprecatedModuleClass : Int = 42
"""
.trimIndent(),
JavaCodeGeneratorOptions(generateJavadoc = generateJavadoc),
generateJavadoc = generateJavadoc
)
assertThat(javaCode)
@@ -372,7 +389,7 @@ class JavaCodeGeneratorTest {
"""
.trimIndent(),
// no message, so no Javadoc, regardless of flag
JavaCodeGeneratorOptions(generateJavadoc = generateJavadoc),
generateJavadoc = generateJavadoc
)
assertThat(javaCode)
@@ -407,7 +424,7 @@ class JavaCodeGeneratorTest {
}
"""
.trimIndent(),
JavaCodeGeneratorOptions(generateGetters = true),
generateGetters = true
)
assertThat(javaCode)
@@ -496,7 +513,7 @@ class JavaCodeGeneratorTest {
@Deprecated { message = "property is deprecated" }
deprecatedProperty: Int
""",
JavaCodeGeneratorOptions(generateJavadoc = true),
generateJavadoc = true
)
assertThat(javaCode)
@@ -564,7 +581,7 @@ class JavaCodeGeneratorTest {
"digit-1" to "DIGIT_1",
"42" to "_42",
"àœü" to "ÀŒÜ",
"日本-つくば" to "日本_つくば",
"日本-つくば" to "日本_つくば"
)
val javaCode =
generateJavaCode(
@@ -586,7 +603,7 @@ class JavaCodeGeneratorTest {
assertThat(field.name).isEqualTo(kotlinName)
Unit
}
},
}
)
assertAll(
@@ -596,7 +613,7 @@ class JavaCodeGeneratorTest {
assertThat(enumConstant.toString()).isEqualTo(pklName)
Unit
}
},
}
)
}
@@ -718,7 +735,7 @@ class JavaCodeGeneratorTest {
}
"""
.trimIndent(),
JavaCodeGeneratorOptions(generateGetters = true),
generateGetters = true
)
assertThat(javaCode)
@@ -872,7 +889,7 @@ class JavaCodeGeneratorTest {
}
"""
.trimIndent(),
JavaCodeGeneratorOptions(generateGetters = true),
generateGetters = true
)
assertThat(javaCode).compilesSuccessfully().isEqualToResourceFile("GenerateGetters.jva")
@@ -985,7 +1002,7 @@ class JavaCodeGeneratorTest {
}
"""
.trimIndent(),
JavaCodeGeneratorOptions(generateJavadoc = true),
generateJavadoc = true
)
assertThat(javaCode).compilesSuccessfully().isEqualToResourceFile("Javadoc.jva")
@@ -1009,7 +1026,8 @@ class JavaCodeGeneratorTest {
}
"""
.trimIndent(),
JavaCodeGeneratorOptions(generateGetters = true, generateJavadoc = true),
generateGetters = true,
generateJavadoc = true
)
assertThat(javaCode)
@@ -1151,7 +1169,7 @@ class JavaCodeGeneratorTest {
foo: String
"""
.trimIndent(),
JavaCodeGeneratorOptions(nonNullAnnotation = "com.example.Annotations\$NonNull"),
nonNullAnnotation = "com.example.Annotations\$NonNull"
)
assertThat(javaCode)
@@ -1445,40 +1463,6 @@ class JavaCodeGeneratorTest {
.contains("public final @NonNull String v6;")
}
@Test
fun `custom constructor parameter annotation`() {
val javaCode =
generateJavaCode(
"""
module my.mod
name: String
"""
.trimIndent(),
JavaCodeGeneratorOptions(paramsAnnotation = "org.project.MyAnnotation"),
)
assertThat(javaCode)
.contains("import org.project.MyAnnotation;")
.contains("public Mod(@MyAnnotation(\"name\") @NonNull String name)")
}
@Test
fun `no constructor parameter annotation`() {
val javaCode =
generateJavaCode(
"""
module my.mod
name: String
"""
.trimIndent(),
JavaCodeGeneratorOptions(paramsAnnotation = null),
)
assertThat(javaCode).contains("public Mod(@NonNull String name)")
}
@Test
fun `spring boot config`() {
val javaCode =
@@ -1494,7 +1478,7 @@ class JavaCodeGeneratorTest {
}
"""
.trimIndent(),
JavaCodeGeneratorOptions(generateSpringBootConfig = true),
generateSpringBootConfig = true
)
assertThat(javaCode)
@@ -1527,7 +1511,6 @@ class JavaCodeGeneratorTest {
.trimMargin()
)
.doesNotContain("@ConstructorBinding")
.doesNotContain("@Named")
// not worthwhile to add spring & spring boot dependency just so that this test can compile
// their annotations
@@ -1548,7 +1531,7 @@ class JavaCodeGeneratorTest {
pigeon: Person
"""
.trimIndent(),
.trimIndent()
)
val client =
@@ -1563,7 +1546,7 @@ class JavaCodeGeneratorTest {
parrot: library.Person
"""
.trimIndent(),
.trimIndent()
)
val javaSourceFiles = generateFiles(library, client)
@@ -1595,7 +1578,7 @@ class JavaCodeGeneratorTest {
pigeon: Person
"""
.trimIndent(),
.trimIndent()
)
val derived =
@@ -1610,7 +1593,7 @@ class JavaCodeGeneratorTest {
person1: Person
person2: Person2
"""
.trimIndent(),
.trimIndent()
)
val javaSourceFiles = generateFiles(base, derived)
@@ -1646,7 +1629,7 @@ class JavaCodeGeneratorTest {
typealias Version = "LATEST"|String
"""
.trimIndent(),
.trimIndent()
)
val derived =
@@ -1659,7 +1642,7 @@ class JavaCodeGeneratorTest {
v: Version = "1.2.3"
"""
.trimIndent(),
.trimIndent()
)
val javaSourceFiles = generateFiles(base, derived)
@@ -1697,7 +1680,7 @@ class JavaCodeGeneratorTest {
prop: Int
}
"""
.trimIndent(),
.trimIndent()
)
val generated = generateFiles(pklModule)
val expectedPropertyFile =
@@ -1730,7 +1713,7 @@ class JavaCodeGeneratorTest {
prop: Int
}
"""
.trimIndent(),
.trimIndent()
)
val generated = generateFiles(pklModule)
val expectedPropertyFile =
@@ -1782,7 +1765,7 @@ class JavaCodeGeneratorTest {
typealias Direction = "north"|"east"|"south"|"west"
"""
.trimIndent(),
JavaCodeGeneratorOptions(implementSerializable = true),
implementSerializable = true
)
assertThat(javaCode)
@@ -1821,7 +1804,7 @@ class JavaCodeGeneratorTest {
smallStruct,
Pattern.compile("(i?)\\w*"),
smallStruct,
enumValue,
enumValue
)
fun confirmSerDe(instance: Any) {
@@ -1863,7 +1846,7 @@ class JavaCodeGeneratorTest {
abstract class Foo { str: String }
"""
.trimIndent(),
JavaCodeGeneratorOptions(implementSerializable = true),
implementSerializable = true
)
assertThat(javaCode).doesNotContain("Serializable")
@@ -1874,7 +1857,7 @@ class JavaCodeGeneratorTest {
module my.mod
"""
.trimIndent(),
JavaCodeGeneratorOptions(implementSerializable = true),
implementSerializable = true
)
assertThat(javaCode).doesNotContain("Serializable")
@@ -1891,7 +1874,7 @@ class JavaCodeGeneratorTest {
class Address { city: String }
"""
.trimIndent(),
JavaCodeGeneratorOptions(implementSerializable = true),
implementSerializable = true
)
assertThat(javaCode)
@@ -1977,7 +1960,7 @@ class JavaCodeGeneratorTest {
}
"""
.trimIndent(),
JavaCodeGeneratorOptions(generateGetters = true),
generateGetters = true
)
assertThat(javaCode)
@@ -2004,7 +1987,7 @@ class JavaCodeGeneratorTest {
@Test
fun `override names in a standalone module`() {
val files =
JavaCodeGeneratorOptions(
JavaCodegenOptions(
renames = mapOf("a.b.c." to "x.y.z.", "d.e.f.AnotherModule" to "u.v.w.RenamedModule")
)
.generateFiles(
@@ -2021,7 +2004,7 @@ class JavaCodeGeneratorTest {
bar: Int = 123
"""
.trimIndent(),
.trimIndent()
)
.toMutableMap()
@@ -2040,7 +2023,7 @@ class JavaCodeGeneratorTest {
@Test
fun `override names based on the longest prefix`() {
val files =
JavaCodeGeneratorOptions(
JavaCodegenOptions(
renames = mapOf("com.foo.bar." to "x.", "com.foo." to "y.", "com." to "z.", "" to "w.")
)
.generateFiles(
@@ -2064,7 +2047,7 @@ class JavaCodeGeneratorTest {
baz: String
"""
.trimIndent(),
.trimIndent()
)
files.validateContents(
@@ -2085,12 +2068,12 @@ class JavaCodeGeneratorTest {
@Test
fun `override names in multiple modules using each other`() {
val files =
JavaCodeGeneratorOptions(
JavaCodegenOptions(
renames =
mapOf(
"org.foo." to "com.foo.x.",
"org.bar.Module2" to "org.bar.RenamedModule",
"org.baz." to "com.baz.a.b.",
"org.baz." to "com.baz.a.b."
)
)
.generateFiles(
@@ -2125,7 +2108,7 @@ class JavaCodeGeneratorTest {
owner: Module2.Group
}
"""
.trimIndent(),
.trimIndent()
)
files.validateContents(
@@ -2141,7 +2124,7 @@ class JavaCodeGeneratorTest {
"package org.bar;",
"import com.foo.x.Module1;",
"public final class RenamedModule {",
"public final Module1. @NonNull Person owner;",
"public final Module1. @NonNull Person owner;"
),
"$MAPPER_PREFIX/org.bar.Module2.properties" to
listOf(
@@ -2154,7 +2137,7 @@ class JavaCodeGeneratorTest {
"package com.baz.a.b;",
"import org.bar.RenamedModule;",
"public final class Module3 {",
"public final RenamedModule. @NonNull Group owner;",
"public final RenamedModule. @NonNull Group owner;"
),
"$MAPPER_PREFIX/org.baz.Module3.properties" to
listOf(
@@ -2167,7 +2150,7 @@ class JavaCodeGeneratorTest {
@Test
fun `do not capitalize names of renamed classes`() {
val files =
JavaCodeGeneratorOptions(
JavaCodegenOptions(
renames = mapOf("a.b.c.MyModule" to "x.y.z.renamed_module", "d.e.f." to "u.v.w.")
)
.generateFiles(
@@ -2184,7 +2167,7 @@ class JavaCodeGeneratorTest {
bar: Int = 123
"""
.trimIndent(),
.trimIndent()
)
files.validateContents(
@@ -2255,9 +2238,7 @@ class JavaCodeGeneratorTest {
assertThat(files).isEmpty()
}
private fun JavaCodeGeneratorOptions.generateFiles(
vararg pklModules: PklModule
): Map<String, String> {
private fun JavaCodegenOptions.generateFiles(vararg pklModules: PklModule): Map<String, String> {
val pklFiles = pklModules.map { it.writeToDisk(tempDir.resolve("pkl/${it.name}.pkl")) }
val evaluator = Evaluator.preconfigured()
return pklFiles.fold(mapOf()) { acc, pklFile ->
@@ -2267,13 +2248,13 @@ class JavaCodeGeneratorTest {
}
}
private fun JavaCodeGeneratorOptions.generateFiles(
private fun JavaCodegenOptions.generateFiles(
vararg pklModules: kotlin.Pair<String, String>
): Map<String, String> =
generateFiles(*pklModules.map { (name, text) -> PklModule(name, text) }.toTypedArray())
private fun generateFiles(vararg pklModules: PklModule): Map<String, JavaSourceCode> =
JavaCodeGeneratorOptions().generateFiles(*pklModules).mapValues { JavaSourceCode(it.value) }
JavaCodegenOptions().generateFiles(*pklModules).mapValues { JavaSourceCode(it.value) }
private fun instantiateOtherAndPropertyTypes(): kotlin.Pair<Any, Any> {
val otherCtor = propertyTypesClasses.getValue("my.Mod\$Other").constructors.first()
@@ -2312,7 +2293,7 @@ class JavaCodeGeneratorTest {
Pattern.compile("(i?)\\w*"),
other,
other,
enumValue,
enumValue
)
return other to propertyTypes

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
package org.pkl.codegen.java
import java.nio.file.Path
import kotlin.io.path.createParentDirectories
import org.pkl.commons.createParentDirectories
import org.pkl.commons.writeString
data class PklModule(val name: String, val content: String) {

Some files were not shown because too many files have changed in this diff Show More