mirror of
https://github.com/apple/pkl.git
synced 2026-07-09 06:25:16 +02:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a7f3abc50 | |||
| 25d86db416 | |||
| 997cfc9ae2 | |||
| 9916c23cfc | |||
| c3d570c769 | |||
| 7499a89d83 | |||
| 010d971af0 | |||
| bd83e29641 | |||
| 2ec62c99a7 | |||
| 3fc97d8dad | |||
| eaf73af247 | |||
| 2ec83198f5 | |||
| 26c115aea6 | |||
| 6a4d3acf21 | |||
| 08b0975af9 | |||
| 1ad63d32b3 | |||
| f44ff9904d | |||
| 45912c504f | |||
| 1c1a39e37f | |||
| bfa6a989be | |||
| 70fc1d4ba3 | |||
| 139d1ae8ec | |||
| 742a8e88da | |||
| 6239981869 | |||
| f470903389 | |||
| 158f709ed4 | |||
| 601a8f424c | |||
| 34c58efe4c | |||
| 7903a072ea | |||
| bda36f0c32 | |||
| d42e199da3 | |||
| f61a5cf541 | |||
| dd6939ab3f | |||
| f7cac257ad | |||
| 1bf00b84ea | |||
| 15f089b275 | |||
| 8a43e51e6b | |||
| b3015a09cc | |||
| ffc755f9c1 | |||
| 112a89468f | |||
| bfac0d66ed | |||
| fc8fe86e5a |
Generated
+2
-2
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: nothing
|
||||
steps:
|
||||
- name: EnricoMi/publish-unit-test-result-action@v2
|
||||
uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
|
||||
uses: EnricoMi/publish-unit-test-result-action@d0a4676d0e0b938bc201470d88276b7c74c712b3 # v2
|
||||
- name: actions/checkout@v6
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
- name: actions/create-github-app-token@v2
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
- name: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
|
||||
- name: actions/setup-java@v5
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
- name: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
||||
- name: dawidd6/action-download-artifact@v11
|
||||
|
||||
Generated
+18
-18
@@ -23,7 +23,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -103,7 +103,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -130,7 +130,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -170,7 +170,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -220,7 +220,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -266,7 +266,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -317,7 +317,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -363,7 +363,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -411,7 +411,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -529,7 +529,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -576,7 +576,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -622,7 +622,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -673,7 +673,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -719,7 +719,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -767,7 +767,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -885,7 +885,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -949,7 +949,7 @@ jobs:
|
||||
pattern: test-results-xml-*
|
||||
- name: Publish test results
|
||||
if: '!cancelled()'
|
||||
uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
|
||||
uses: EnricoMi/publish-unit-test-result-action@d0a4676d0e0b938bc201470d88276b7c74c712b3 # v2
|
||||
with:
|
||||
comment_mode: 'off'
|
||||
files: test-results-xml-*/**/*.xml
|
||||
|
||||
Generated
+20
-20
@@ -21,7 +21,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -168,7 +168,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -218,7 +218,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -264,7 +264,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -315,7 +315,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -361,7 +361,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -409,7 +409,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -527,7 +527,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -574,7 +574,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -620,7 +620,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -671,7 +671,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -717,7 +717,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -765,7 +765,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -883,7 +883,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -946,7 +946,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -983,7 +983,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -1018,7 +1018,7 @@ jobs:
|
||||
pattern: test-results-xml-*
|
||||
- name: Publish test results
|
||||
if: '!cancelled()'
|
||||
uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
|
||||
uses: EnricoMi/publish-unit-test-result-action@d0a4676d0e0b938bc201470d88276b7c74c712b3 # v2
|
||||
with:
|
||||
comment_mode: 'off'
|
||||
files: test-results-xml-*/**/*.xml
|
||||
|
||||
Generated
+14
-14
@@ -17,7 +17,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -103,7 +103,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -151,7 +151,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -203,7 +203,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -251,7 +251,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -301,7 +301,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -421,7 +421,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -469,7 +469,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -517,7 +517,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -569,7 +569,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -617,7 +617,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -667,7 +667,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -787,7 +787,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
|
||||
Generated
+18
-18
@@ -21,7 +21,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -168,7 +168,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -218,7 +218,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -264,7 +264,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -315,7 +315,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -361,7 +361,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -409,7 +409,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -527,7 +527,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -574,7 +574,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -620,7 +620,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -671,7 +671,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -717,7 +717,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -765,7 +765,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -883,7 +883,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -947,7 +947,7 @@ jobs:
|
||||
pattern: test-results-xml-*
|
||||
- name: Publish test results
|
||||
if: '!cancelled()'
|
||||
uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
|
||||
uses: EnricoMi/publish-unit-test-result-action@d0a4676d0e0b938bc201470d88276b7c74c712b3 # v2
|
||||
with:
|
||||
comment_mode: 'off'
|
||||
files: test-results-xml-*/**/*.xml
|
||||
|
||||
Generated
+19
-19
@@ -21,7 +21,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -168,7 +168,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -219,7 +219,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -266,7 +266,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -318,7 +318,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -365,7 +365,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -414,7 +414,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -533,7 +533,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -581,7 +581,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -628,7 +628,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -680,7 +680,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -727,7 +727,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -776,7 +776,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -895,7 +895,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -959,7 +959,7 @@ jobs:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: temurin
|
||||
@@ -1043,7 +1043,7 @@ jobs:
|
||||
pattern: test-results-xml-*
|
||||
- name: Publish test results
|
||||
if: '!cancelled()'
|
||||
uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
|
||||
uses: EnricoMi/publish-unit-test-result-action@d0a4676d0e0b938bc201470d88276b7c74c712b3 # v2
|
||||
with:
|
||||
comment_mode: 'off'
|
||||
files: test-results-xml-*/**/*.xml
|
||||
|
||||
Generated
+1
-1
@@ -25,7 +25,7 @@ jobs:
|
||||
name_is_regexp: true
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
- name: Publish test results
|
||||
uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
|
||||
uses: EnricoMi/publish-unit-test-result-action@d0a4676d0e0b938bc201470d88276b7c74c712b3 # v2
|
||||
with:
|
||||
commit: ${{ github.event.workflow_run.head_sha }}
|
||||
comment_mode: 'off'
|
||||
|
||||
@@ -19,8 +19,8 @@ plugins {
|
||||
id("me.champeau.jmh")
|
||||
}
|
||||
|
||||
val truffle: Configuration by configurations.creating
|
||||
val graal: Configuration by configurations.creating
|
||||
val truffle: Configuration = configurations.create("truffle")
|
||||
val graal: Configuration = configurations.create("graal")
|
||||
|
||||
dependencies {
|
||||
jmh(projects.pklCore)
|
||||
|
||||
@@ -13,10 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import java.nio.file.AtomicMoveNotSupportedException
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.util.*
|
||||
import java.util.zip.ZipInputStream
|
||||
import javax.inject.Inject
|
||||
import kotlin.io.path.createDirectories
|
||||
import org.gradle.api.DefaultTask
|
||||
@@ -41,19 +44,14 @@ constructor(
|
||||
@TaskAction
|
||||
@Suppress("unused")
|
||||
fun run() {
|
||||
// minimize chance of corruption by extract-to-random-dir-and-flip-symlink
|
||||
// minimize chance of corruption by extract-to-random-dir-and-publish
|
||||
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()
|
||||
if (os.isWindows) extractZip(distroDir) else extractTarGz(distroDir)
|
||||
|
||||
val distroBinDir =
|
||||
if (os.isMacOsX) distroDir.resolve("Contents/Home/bin") else distroDir.resolve("bin")
|
||||
|
||||
@@ -70,17 +68,7 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
publishInstallDir(distroDir, os)
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
fileOperations.delete(distroDir)
|
||||
@@ -88,4 +76,75 @@ constructor(
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractTarGz(distroDir: Path) {
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractZip(distroDir: Path) {
|
||||
val targetDir = distroDir.toAbsolutePath().normalize()
|
||||
ZipInputStream(graalVm.get().downloadFile.inputStream().buffered()).use { zipInput ->
|
||||
var entry = zipInput.nextEntry
|
||||
while (entry != null) {
|
||||
try {
|
||||
val strippedPath = stripFirstPathComponent(entry.name)
|
||||
if (strippedPath != null) {
|
||||
val target = targetDir.resolve(strippedPath).normalize()
|
||||
require(target.startsWith(targetDir)) {
|
||||
"GraalVM archive entry escapes destination directory: ${entry.name}"
|
||||
}
|
||||
if (entry.isDirectory) {
|
||||
target.createDirectories()
|
||||
} else {
|
||||
target.parent?.createDirectories()
|
||||
Files.copy(zipInput, target)
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
zipInput.closeEntry()
|
||||
}
|
||||
entry = zipInput.nextEntry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun stripFirstPathComponent(path: String): String? {
|
||||
val normalizedPath = path.replace('\\', '/').trimStart('/')
|
||||
val separatorIndex = normalizedPath.indexOf('/')
|
||||
if (separatorIndex == -1) return null
|
||||
return normalizedPath.substring(separatorIndex + 1).takeIf { it.isNotEmpty() }
|
||||
}
|
||||
|
||||
private fun publishInstallDir(distroDir: Path, os: org.gradle.internal.os.OperatingSystem) {
|
||||
if (os.isWindows) {
|
||||
println("Installing ${graalVm.get().installDir} from $distroDir")
|
||||
moveAtomicallyOrRegularly(distroDir, graalVm.get().installDir.toPath())
|
||||
return
|
||||
}
|
||||
|
||||
println("Creating symlink ${graalVm.get().installDir} for $distroDir")
|
||||
val tempLink = Paths.get(graalVm.get().homeDir, UUID.randomUUID().toString())
|
||||
Files.createSymbolicLink(tempLink, distroDir)
|
||||
try {
|
||||
moveAtomicallyOrRegularly(tempLink, graalVm.get().installDir.toPath())
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
fileOperations.delete(tempLink.toFile())
|
||||
} catch (ignored: Exception) {}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
private fun moveAtomicallyOrRegularly(source: Path, target: Path) {
|
||||
try {
|
||||
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE)
|
||||
} catch (e: AtomicMoveNotSupportedException) {
|
||||
Files.move(source, target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,11 +63,13 @@ fun Project.configurePklPomMetadata() {
|
||||
|
||||
/** Configures POM validation task to check for unresolved versions and snapshots in releases. */
|
||||
fun Project.configurePomValidation() {
|
||||
val validatePom by tasks.registering {
|
||||
val validatePom =
|
||||
tasks.register("validatePom") {
|
||||
if (tasks.findByName("generatePomFileForLibraryPublication") == null) {
|
||||
return@registering
|
||||
return@register
|
||||
}
|
||||
val generatePomFileForLibraryPublication by tasks.existing(GenerateMavenPom::class)
|
||||
val generatePomFileForLibraryPublication =
|
||||
tasks.named<GenerateMavenPom>("generatePomFileForLibraryPublication")
|
||||
val outputFile =
|
||||
layout.buildDirectory.file("validatePom") // dummy output to satisfy up-to-date check
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ plugins.withType(MavenPublishPlugin::class).configureEach {
|
||||
}
|
||||
}
|
||||
|
||||
val allDependencies by tasks.registering(DependencyReportTask::class)
|
||||
val allDependencies = tasks.register<DependencyReportTask>("allDependencies")
|
||||
|
||||
tasks.withType(Test::class).configureEach {
|
||||
System.getProperty("testReportsDir")?.let { reportsDir ->
|
||||
|
||||
@@ -132,8 +132,8 @@ tasks.shadowJar {
|
||||
|
||||
shadow { addShadowVariantIntoJavaComponent = false }
|
||||
|
||||
val testFatJar by
|
||||
tasks.registering(Test::class) {
|
||||
val testFatJar =
|
||||
tasks.register<Test>("testFatJar") {
|
||||
testClassesDirs = files(tasks.test.get().testClassesDirs)
|
||||
classpath =
|
||||
// compiled test classes
|
||||
@@ -148,7 +148,8 @@ val testFatJar by
|
||||
|
||||
tasks.check { dependsOn(testFatJar) }
|
||||
|
||||
val validateFatJar by tasks.registering {
|
||||
val validateFatJar =
|
||||
tasks.register("validateFatJar") {
|
||||
val outputFile = layout.buildDirectory.file("validateFatJar/result.txt")
|
||||
inputs.files(tasks.shadowJar)
|
||||
inputs.property("nonRelocations", nonRelocations)
|
||||
@@ -177,18 +178,18 @@ val validateFatJar by tasks.registering {
|
||||
throw GradleException("Found unshadowed files:\n" + unshadowedFiles.joinToString("\n"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.check { dependsOn(validateFatJar) }
|
||||
|
||||
val resolveSourcesJars by
|
||||
tasks.registering(ResolveSourcesJars::class) {
|
||||
val resolveSourcesJars =
|
||||
tasks.register<ResolveSourcesJars>("resolveSourcesJars") {
|
||||
configuration.set(configurations.runtimeClasspath)
|
||||
outputDir.set(layout.buildDirectory.dir("resolveSourcesJars"))
|
||||
}
|
||||
|
||||
val fatSourcesJar by
|
||||
tasks.registering(MergeSourcesJars::class) {
|
||||
val fatSourcesJar =
|
||||
tasks.register<MergeSourcesJars>("fatSourcesJar") {
|
||||
plugins.withId("pklJavaLibrary") { inputJars.from(tasks.named("sourcesJar")) }
|
||||
inputJars.from(firstPartySourcesJarsConfiguration)
|
||||
inputJars.from(resolveSourcesJars.map { fileTree(it.outputDir) })
|
||||
@@ -213,7 +214,7 @@ publishing {
|
||||
artifact(fatSourcesJar.flatMap { it.outputJar.asFile }) { classifier = "sources" }
|
||||
|
||||
plugins.withId("pklJavaLibrary") {
|
||||
val javadocJar by tasks.existing(Jar::class)
|
||||
val javadocJar = tasks.named<Jar>("javadocJar")
|
||||
// Javadoc Jar is not fat (didn't invest effort)
|
||||
artifact(javadocJar.flatMap { it.archiveFile }) { classifier = "javadoc" }
|
||||
}
|
||||
|
||||
@@ -21,11 +21,15 @@ plugins { id("de.undercouch.download") }
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
// tries to minimize chance of corruption by download-to-temp-file-and-move
|
||||
val downloadGraalVmAarch64 by
|
||||
tasks.registering(Download::class) { configureDownloadGraalVm(buildInfo.graalVmAarch64) }
|
||||
val downloadGraalVmAarch64 =
|
||||
tasks.register<Download>("downloadGraalVmAarch64") {
|
||||
configureDownloadGraalVm(buildInfo.graalVmAarch64)
|
||||
}
|
||||
|
||||
val downloadGraalVmAmd64 by
|
||||
tasks.registering(Download::class) { configureDownloadGraalVm(buildInfo.graalVmAmd64) }
|
||||
val downloadGraalVmAmd64 =
|
||||
tasks.register<Download>("downloadGraalVmAmd64") {
|
||||
configureDownloadGraalVm(buildInfo.graalVmAmd64)
|
||||
}
|
||||
|
||||
fun Download.configureDownloadGraalVm(graalvm: BuildInfo.GraalVm) {
|
||||
onlyIf { !graalvm.installDir.exists() }
|
||||
@@ -37,14 +41,14 @@ fun Download.configureDownloadGraalVm(graalvm: BuildInfo.GraalVm) {
|
||||
tempAndMove(true)
|
||||
}
|
||||
|
||||
val verifyGraalVmAarch64 by
|
||||
tasks.registering(Verify::class) {
|
||||
val verifyGraalVmAarch64 =
|
||||
tasks.register<Verify>("verifyGraalVmAarch64") {
|
||||
configureVerifyGraalVm(buildInfo.graalVmAarch64)
|
||||
dependsOn(downloadGraalVmAarch64)
|
||||
}
|
||||
|
||||
val verifyGraalVmAmd64 by
|
||||
tasks.registering(Verify::class) {
|
||||
val verifyGraalVmAmd64 =
|
||||
tasks.register<Verify>("verifyGraalVmAmd64") {
|
||||
configureVerifyGraalVm(buildInfo.graalVmAmd64)
|
||||
dependsOn(downloadGraalVmAmd64)
|
||||
}
|
||||
@@ -60,15 +64,15 @@ fun Verify.configureVerifyGraalVm(graalvm: BuildInfo.GraalVm) {
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
val installGraalVmAarch64 by
|
||||
tasks.registering(InstallGraalVm::class) {
|
||||
val installGraalVmAarch64 =
|
||||
tasks.register<InstallGraalVm>("installGraalVmAarch64") {
|
||||
dependsOn(verifyGraalVmAarch64)
|
||||
graalVm = buildInfo.graalVmAarch64
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
val installGraalVmAmd64 by
|
||||
tasks.registering(InstallGraalVm::class) {
|
||||
val installGraalVmAmd64 =
|
||||
tasks.register<InstallGraalVm>("installGraalVmAmd64") {
|
||||
dependsOn(verifyGraalVmAmd64)
|
||||
graalVm = buildInfo.graalVmAmd64
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ dependencies {
|
||||
}
|
||||
}
|
||||
|
||||
val validateHtml by
|
||||
tasks.registering(JavaExec::class) {
|
||||
val validateHtml =
|
||||
tasks.register<JavaExec>("validateHtml") {
|
||||
val resultFile = layout.buildDirectory.file("validateHtml/result.txt")
|
||||
inputs.files(htmlValidator.sources)
|
||||
outputs.file(resultFile)
|
||||
|
||||
@@ -26,8 +26,8 @@ plugins {
|
||||
val executableSpec = project.extensions.create("executable", ExecutableSpec::class.java)
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
val javaExecutable by
|
||||
tasks.registering(ExecutableJar::class) {
|
||||
val javaExecutable =
|
||||
tasks.register<ExecutableJar>("javaExecutable") {
|
||||
group = "build"
|
||||
dependsOn(tasks.jar)
|
||||
inJar = tasks.shadowJar.flatMap { it.archiveFile }
|
||||
@@ -77,7 +77,8 @@ fun Task.setupTestStartJavaExecutable(launcher: Provider<JavaLauncher>? = null)
|
||||
}
|
||||
}
|
||||
|
||||
val testStartJavaExecutable by tasks.registering { setupTestStartJavaExecutable() }
|
||||
val testStartJavaExecutable =
|
||||
tasks.register("testStartJavaExecutable") { setupTestStartJavaExecutable() }
|
||||
|
||||
// Setup `testStartJavaExecutable` tasks for multi-JDK testing.
|
||||
val testStartJavaExecutableOnOtherJdks =
|
||||
|
||||
@@ -30,14 +30,18 @@ plugins {
|
||||
val executableSpec = project.extensions.getByType<ExecutableSpec>()
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
val stagedMacAmd64Executable: Configuration by configurations.creating
|
||||
val stagedMacAarch64Executable: Configuration by configurations.creating
|
||||
val stagedLinuxAmd64Executable: Configuration by configurations.creating
|
||||
val stagedLinuxAarch64Executable: Configuration by configurations.creating
|
||||
val stagedAlpineLinuxAmd64Executable: Configuration by configurations.creating
|
||||
val stagedWindowsAmd64Executable: Configuration by configurations.creating
|
||||
val stagedMacAmd64Executable: Configuration = configurations.create("stagedMacAmd64Executable")
|
||||
val stagedMacAarch64Executable: Configuration = configurations.create("stagedMacAarch64Executable")
|
||||
val stagedLinuxAmd64Executable: Configuration = configurations.create("stagedLinuxAmd64Executable")
|
||||
val stagedLinuxAarch64Executable: Configuration =
|
||||
configurations.create("stagedLinuxAarch64Executable")
|
||||
val stagedAlpineLinuxAmd64Executable: Configuration =
|
||||
configurations.create("stagedAlpineLinuxAmd64Executable")
|
||||
val stagedWindowsAmd64Executable: Configuration =
|
||||
configurations.create("stagedWindowsAmd64Executable")
|
||||
|
||||
val nativeImageClasspath by configurations.creating {
|
||||
val nativeImageClasspath =
|
||||
configurations.create("nativeImageClasspath") {
|
||||
extendsFrom(configurations.runtimeClasspath.get())
|
||||
// Ensure native-image version uses GraalVM C SDKs instead of Java FFI or JNA
|
||||
// (comes from artifact `mordant-jvm-graal-ffi`).
|
||||
@@ -45,7 +49,7 @@ val nativeImageClasspath by configurations.creating {
|
||||
exclude("com.github.ajalt.mordant", "mordant-jvm-ffm-jvm")
|
||||
exclude("com.github.ajalt.mordant", "mordant-jvm-jna")
|
||||
exclude("com.github.ajalt.mordant", "mordant-jvm-jna-jvm")
|
||||
}
|
||||
}
|
||||
|
||||
val libs = the<LibrariesForLibs>()
|
||||
|
||||
@@ -85,32 +89,32 @@ private fun NativeImageBuild.setClasspath() {
|
||||
classpath.from(nativeImageClasspath)
|
||||
}
|
||||
|
||||
val macExecutableAmd64 by
|
||||
tasks.registering(NativeImageBuild::class) {
|
||||
val macExecutableAmd64 =
|
||||
tasks.register<NativeImageBuild>("macExecutableAmd64") {
|
||||
imageName = executableSpec.name.map { "$it-macos-amd64" }
|
||||
mainClass = executableSpec.mainClass
|
||||
amd64()
|
||||
setClasspath()
|
||||
}
|
||||
|
||||
val macExecutableAarch64 by
|
||||
tasks.registering(NativeImageBuild::class) {
|
||||
val macExecutableAarch64 =
|
||||
tasks.register<NativeImageBuild>("macExecutableAarch64") {
|
||||
imageName = executableSpec.name.map { "$it-macos-aarch64" }
|
||||
mainClass = executableSpec.mainClass
|
||||
aarch64()
|
||||
setClasspath()
|
||||
}
|
||||
|
||||
val linuxExecutableAmd64 by
|
||||
tasks.registering(NativeImageBuild::class) {
|
||||
val linuxExecutableAmd64 =
|
||||
tasks.register<NativeImageBuild>("linuxExecutableAmd64") {
|
||||
imageName = executableSpec.name.map { "$it-linux-amd64" }
|
||||
mainClass = executableSpec.mainClass
|
||||
amd64()
|
||||
setClasspath()
|
||||
}
|
||||
|
||||
val linuxExecutableAarch64 by
|
||||
tasks.registering(NativeImageBuild::class) {
|
||||
val linuxExecutableAarch64 =
|
||||
tasks.register<NativeImageBuild>("linuxExecutableAarch64") {
|
||||
imageName = executableSpec.name.map { "$it-linux-aarch64" }
|
||||
mainClass = executableSpec.mainClass
|
||||
aarch64()
|
||||
@@ -120,8 +124,8 @@ val linuxExecutableAarch64 by
|
||||
extraNativeImageArgs.add("-H:PageSize=65536")
|
||||
}
|
||||
|
||||
val alpineExecutableAmd64 by
|
||||
tasks.registering(NativeImageBuild::class) {
|
||||
val alpineExecutableAmd64 =
|
||||
tasks.register<NativeImageBuild>("alpineExecutableAmd64") {
|
||||
imageName = executableSpec.name.map { "$it-alpine-linux-amd64" }
|
||||
mainClass = executableSpec.mainClass
|
||||
amd64()
|
||||
@@ -129,17 +133,18 @@ val alpineExecutableAmd64 by
|
||||
extraNativeImageArgs.addAll(listOf("--static", "--libc=musl"))
|
||||
}
|
||||
|
||||
val windowsExecutableAmd64 by
|
||||
tasks.registering(NativeImageBuild::class) {
|
||||
val windowsExecutableAmd64 =
|
||||
tasks.register<NativeImageBuild>("windowsExecutableAmd64") {
|
||||
imageName = executableSpec.name.map { "$it-windows-amd64" }
|
||||
mainClass = executableSpec.mainClass
|
||||
amd64()
|
||||
setClasspath()
|
||||
}
|
||||
|
||||
val assembleNative by tasks.existing
|
||||
val assembleNative = tasks.named("assembleNative")
|
||||
|
||||
val testStartNativeExecutable by tasks.registering {
|
||||
val testStartNativeExecutable =
|
||||
tasks.register("testStartNativeExecutable") {
|
||||
dependsOn(assembleNative)
|
||||
|
||||
// dummy file for up-to-date checking
|
||||
@@ -164,11 +169,12 @@ val testStartNativeExecutable by tasks.registering {
|
||||
writeText("OK")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val requiredGlibcVersion: Version = Version.parse("2.17")
|
||||
|
||||
val checkGlibc by tasks.registering {
|
||||
val checkGlibc =
|
||||
tasks.register("checkGlibc") {
|
||||
enabled = buildInfo.os.isLinux && !buildInfo.musl
|
||||
dependsOn(assembleNative)
|
||||
doLast {
|
||||
@@ -195,7 +201,7 @@ val checkGlibc by tasks.registering {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expose underlying task's outputs
|
||||
private fun <T : Task> Task.wraps(other: TaskProvider<T>) {
|
||||
@@ -203,19 +209,24 @@ private fun <T : Task> Task.wraps(other: TaskProvider<T>) {
|
||||
outputs.files(other)
|
||||
}
|
||||
|
||||
val testNative by tasks.existing { dependsOn(testStartNativeExecutable, checkGlibc) }
|
||||
val testNative = tasks.named("testNative") { dependsOn(testStartNativeExecutable, checkGlibc) }
|
||||
|
||||
val assembleNativeMacOsAarch64 by tasks.existing { wraps(macExecutableAarch64) }
|
||||
val assembleNativeMacOsAarch64 =
|
||||
tasks.named("assembleNativeMacOsAarch64") { wraps(macExecutableAarch64) }
|
||||
|
||||
val assembleNativeMacOsAmd64 by tasks.existing { wraps(macExecutableAmd64) }
|
||||
val assembleNativeMacOsAmd64 = tasks.named("assembleNativeMacOsAmd64") { wraps(macExecutableAmd64) }
|
||||
|
||||
val assembleNativeLinuxAarch64 by tasks.existing { wraps(linuxExecutableAarch64) }
|
||||
val assembleNativeLinuxAarch64 =
|
||||
tasks.named("assembleNativeLinuxAarch64") { wraps(linuxExecutableAarch64) }
|
||||
|
||||
val assembleNativeLinuxAmd64 by tasks.existing { wraps(linuxExecutableAmd64) }
|
||||
val assembleNativeLinuxAmd64 =
|
||||
tasks.named("assembleNativeLinuxAmd64") { wraps(linuxExecutableAmd64) }
|
||||
|
||||
val assembleNativeAlpineLinuxAmd64 by tasks.existing { wraps(alpineExecutableAmd64) }
|
||||
val assembleNativeAlpineLinuxAmd64 =
|
||||
tasks.named("assembleNativeAlpineLinuxAmd64") { wraps(alpineExecutableAmd64) }
|
||||
|
||||
val assembleNativeWindowsAmd64 by tasks.existing { wraps(windowsExecutableAmd64) }
|
||||
val assembleNativeWindowsAmd64 =
|
||||
tasks.named("assembleNativeWindowsAmd64") { wraps(windowsExecutableAmd64) }
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
|
||||
@@ -13,29 +13,31 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
val assembleNativeMacOsAarch64 by tasks.registering { group = "build" }
|
||||
val assembleNativeMacOsAarch64 = tasks.register("assembleNativeMacOsAarch64") { group = "build" }
|
||||
|
||||
val assembleNativeMacOsAmd64 by tasks.registering { group = "build" }
|
||||
val assembleNativeMacOsAmd64 = tasks.register("assembleNativeMacOsAmd64") { group = "build" }
|
||||
|
||||
val assembleNativeLinuxAarch64 by tasks.registering { group = "build" }
|
||||
val assembleNativeLinuxAarch64 = tasks.register("assembleNativeLinuxAarch64") { group = "build" }
|
||||
|
||||
val assembleNativeLinuxAmd64 by tasks.registering { group = "build" }
|
||||
val assembleNativeLinuxAmd64 = tasks.register("assembleNativeLinuxAmd64") { group = "build" }
|
||||
|
||||
val assembleNativeAlpineLinuxAmd64 by tasks.registering { group = "build" }
|
||||
val assembleNativeAlpineLinuxAmd64 =
|
||||
tasks.register("assembleNativeAlpineLinuxAmd64") { group = "build" }
|
||||
|
||||
val assembleNativeWindowsAmd64 by tasks.registering { group = "build" }
|
||||
val assembleNativeWindowsAmd64 = tasks.register("assembleNativeWindowsAmd64") { group = "build" }
|
||||
|
||||
val testNativeMacOsAarch64 by tasks.registering { group = "verification" }
|
||||
val testNativeMacOsAarch64 = tasks.register("testNativeMacOsAarch64") { group = "verification" }
|
||||
|
||||
val testNativeMacOsAmd64 by tasks.registering { group = "verification" }
|
||||
val testNativeMacOsAmd64 = tasks.register("testNativeMacOsAmd64") { group = "verification" }
|
||||
|
||||
val testNativeLinuxAarch64 by tasks.registering { group = "verification" }
|
||||
val testNativeLinuxAarch64 = tasks.register("testNativeLinuxAarch64") { group = "verification" }
|
||||
|
||||
val testNativeLinuxAmd64 by tasks.registering { group = "verification" }
|
||||
val testNativeLinuxAmd64 = tasks.register("testNativeLinuxAmd64") { group = "verification" }
|
||||
|
||||
val testNativeAlpineLinuxAmd64 by tasks.registering { group = "verification" }
|
||||
val testNativeAlpineLinuxAmd64 =
|
||||
tasks.register("testNativeAlpineLinuxAmd64") { group = "verification" }
|
||||
|
||||
val testNativeWindowsAmd64 by tasks.registering { group = "verification" }
|
||||
val testNativeWindowsAmd64 = tasks.register("testNativeWindowsAmd64") { group = "verification" }
|
||||
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
@@ -44,7 +46,8 @@ private fun <T : Task> Task.wraps(other: TaskProvider<T>) {
|
||||
outputs.files(other)
|
||||
}
|
||||
|
||||
val assembleNative by tasks.registering {
|
||||
val assembleNative =
|
||||
tasks.register("assembleNative") {
|
||||
group = "build"
|
||||
|
||||
if (!buildInfo.isCrossArchSupported && buildInfo.isCrossArch) {
|
||||
@@ -62,7 +65,8 @@ val assembleNative by tasks.registering {
|
||||
wraps(assembleNativeLinuxAarch64)
|
||||
}
|
||||
buildInfo.os.isLinux && buildInfo.targetArch == "amd64" -> {
|
||||
if (buildInfo.musl) wraps(assembleNativeAlpineLinuxAmd64) else wraps(assembleNativeLinuxAmd64)
|
||||
if (buildInfo.musl) wraps(assembleNativeAlpineLinuxAmd64)
|
||||
else wraps(assembleNativeLinuxAmd64)
|
||||
}
|
||||
buildInfo.os.isWindows && buildInfo.targetArch == "amd64" -> {
|
||||
wraps(assembleNativeWindowsAmd64)
|
||||
@@ -75,9 +79,10 @@ val assembleNative by tasks.registering {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val testNative by tasks.registering {
|
||||
val testNative =
|
||||
tasks.register("testNative") {
|
||||
group = "verification"
|
||||
dependsOn(assembleNative)
|
||||
|
||||
@@ -96,7 +101,8 @@ val testNative by tasks.registering {
|
||||
dependsOn(testNativeLinuxAarch64)
|
||||
}
|
||||
buildInfo.os.isLinux && buildInfo.targetArch == "amd64" -> {
|
||||
if (buildInfo.musl) dependsOn(testNativeAlpineLinuxAmd64) else dependsOn(testNativeLinuxAmd64)
|
||||
if (buildInfo.musl) dependsOn(testNativeAlpineLinuxAmd64)
|
||||
else dependsOn(testNativeLinuxAmd64)
|
||||
}
|
||||
buildInfo.os.isWindows && buildInfo.targetArch == "amd64" -> {
|
||||
dependsOn(testNativeWindowsAmd64)
|
||||
@@ -109,14 +115,16 @@ val testNative by tasks.registering {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val checkNative by tasks.registering {
|
||||
val checkNative =
|
||||
tasks.register("checkNative") {
|
||||
group = "verification"
|
||||
dependsOn(testNative)
|
||||
}
|
||||
}
|
||||
|
||||
val buildNative by tasks.registering {
|
||||
val buildNative =
|
||||
tasks.register("buildNative") {
|
||||
group = "build"
|
||||
dependsOn(checkNative)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
plugins { id("com.diffplug.spotless") }
|
||||
|
||||
val pklFormatter by configurations.creating
|
||||
val pklFormatter = configurations.create("pklFormatter")
|
||||
|
||||
dependencies { pklFormatter(rootProject.project("pkl-formatter")) }
|
||||
|
||||
|
||||
+4
-3
@@ -37,7 +37,8 @@ nexusPublishing {
|
||||
}
|
||||
}
|
||||
|
||||
val configureLateInitAnnotation by tasks.registering(ConfigureLateInitAnnotation::class)
|
||||
val configureLateInitAnnotation =
|
||||
tasks.register<ConfigureLateInitAnnotation>("configureLateInitAnnotation")
|
||||
|
||||
idea {
|
||||
project {
|
||||
@@ -53,9 +54,9 @@ idea {
|
||||
}
|
||||
}
|
||||
|
||||
val clean by tasks.existing { delete(layout.buildDirectory) }
|
||||
val clean = tasks.named("clean") { delete(layout.buildDirectory) }
|
||||
|
||||
val printVersion by tasks.registering { doFirst { println(buildInfo.pklVersion) } }
|
||||
val printVersion = tasks.register("printVersion") { doFirst { println(buildInfo.pklVersion) } }
|
||||
|
||||
val message =
|
||||
"""
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
name: main
|
||||
title: Main Project
|
||||
version: 0.32.0-dev
|
||||
version: 0.33.0-dev
|
||||
prerelease: true
|
||||
nav:
|
||||
- nav.adoc
|
||||
|
||||
@@ -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.32.0
|
||||
:pkl-version-no-suffix: 0.33.0
|
||||
// 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:
|
||||
@@ -69,6 +69,7 @@ endif::[]
|
||||
|
||||
:uri-stdlib-baseModule: {uri-pkl-stdlib-docs}/base
|
||||
:uri-stdlib-CommandModule: {uri-pkl-stdlib-docs}/Command
|
||||
:uri-stdlib-refModule: {uri-pkl-stdlib-docs}/ref
|
||||
:uri-stdlib-analyzeModule: {uri-pkl-stdlib-docs}/analyze
|
||||
:uri-stdlib-jsonnetModule: {uri-pkl-stdlib-docs}/jsonnet
|
||||
:uri-stdlib-reflectModule: {uri-pkl-stdlib-docs}/reflect
|
||||
@@ -160,6 +161,8 @@ endif::[]
|
||||
:uri-stdlib-Command-CountedFlag: {uri-stdlib-CommandModule}/CountedFlag
|
||||
:uri-stdlib-Command-Argument: {uri-stdlib-CommandModule}/Argument
|
||||
:uri-stdlib-Command-Import: {uri-stdlib-CommandModule}/Import
|
||||
:uri-stdlib-ref-Reference: {uri-stdlib-baseModule}/Reference
|
||||
:uri-stdlib-ref-Access: {uri-stdlib-baseModule}/Access
|
||||
|
||||
:uri-messagepack: https://msgpack.org/index.html
|
||||
:uri-messagepack-spec: https://github.com/msgpack/msgpack/blob/master/spec.md
|
||||
|
||||
@@ -187,6 +187,15 @@ The array's length is the number of slots that are filled. For example, xref:{ur
|
||||
|
|
||||
|
|
||||
|
|
||||
|
||||
|link:{uri-stdlib-ref-Reference}[Reference]
|
||||
|`0x20`
|
||||
|`<value>` (Typed)
|
||||
|Domain
|
||||
|`<value>`
|
||||
|Data
|
||||
|link:{uri-messagepack-array}[array]
|
||||
|Array of link:{uri-stdlib-ref-Access}[`pkl.ref#Access`] values
|
||||
|===
|
||||
|
||||
[[type-name-encoding]]
|
||||
|
||||
@@ -56,7 +56,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven(url = "{uri-sonatype}")
|
||||
maven(url = "{uri-snapshot-repo}")
|
||||
endif::[]
|
||||
}
|
||||
----
|
||||
@@ -75,7 +75,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven { url "{uri-sonatype}" }
|
||||
maven { url "{uri-snapshot-repo}" }
|
||||
endif::[]
|
||||
}
|
||||
----
|
||||
@@ -99,9 +99,9 @@ ifndef::is-release-version[]
|
||||
<repository>
|
||||
<id>sonatype-s01</id>
|
||||
<name>Sonatype S01</name>
|
||||
<url>{uri-sonatype}</url>
|
||||
<url>{uri-snapshot-repo}</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
</repositories>
|
||||
endif::[]
|
||||
</project>
|
||||
----
|
||||
|
||||
@@ -45,7 +45,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven(url = "{uri-sonatype}")
|
||||
maven(url = "{uri-snapshot-repo}")
|
||||
endif::[]
|
||||
}
|
||||
----
|
||||
@@ -66,7 +66,7 @@ repositories {
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
repositories {
|
||||
maven { url "{uri-sonatype}" }
|
||||
maven { url "{uri-snapshot-repo}" }
|
||||
}
|
||||
endif::[]
|
||||
----
|
||||
@@ -92,7 +92,7 @@ ifndef::is-release-version[]
|
||||
<repository>
|
||||
<id>sonatype-s01</id>
|
||||
<name>Sonatype S01</name>
|
||||
<url>{uri-sonatype}</url>
|
||||
<url>{uri-snapshot-repo}</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
endif::[]
|
||||
|
||||
@@ -46,7 +46,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven(url = "{uri-sonatype}")
|
||||
maven(url = "{uri-snapshot-repo}")
|
||||
endif::[]
|
||||
}
|
||||
----
|
||||
@@ -65,7 +65,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven { url "{uri-sonatype}" }
|
||||
maven { url "{uri-snapshot-repo}" }
|
||||
endif::[]
|
||||
}
|
||||
----
|
||||
|
||||
@@ -34,7 +34,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven(url = "{uri-sonatype}")
|
||||
maven(url = "{uri-snapshot-repo}")
|
||||
endif::[]
|
||||
}
|
||||
----
|
||||
@@ -53,7 +53,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven { url "{uri-sonatype}" }
|
||||
maven { url "{uri-snapshot-repo}" }
|
||||
endif::[]
|
||||
}
|
||||
----
|
||||
@@ -77,7 +77,7 @@ ifndef::is-release-version[]
|
||||
<repository>
|
||||
<id>sonatype-s01</id>
|
||||
<name>Sonatype S01</name>
|
||||
<url>{uri-sonatype}</url>
|
||||
<url>{uri-snapshot-repo}</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
endif::[]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -44,7 +44,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven(url = "{uri-sonatype}")
|
||||
maven(url = "{uri-snapshot-repo}")
|
||||
endif::[]
|
||||
}
|
||||
----
|
||||
@@ -63,7 +63,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven { url "{uri-sonatype}" }
|
||||
maven { url "{uri-snapshot-repo}" }
|
||||
endif::[]
|
||||
}
|
||||
----
|
||||
@@ -87,7 +87,7 @@ ifndef::is-release-version[]
|
||||
<repository>
|
||||
<id>sonatype-s01</id>
|
||||
<name>Sonatype S01</name>
|
||||
<url>{uri-sonatype}</url>
|
||||
<url>{uri-snapshot-repo}</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
endif::[]
|
||||
|
||||
@@ -117,7 +117,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven(url = "{uri-sonatype}")
|
||||
maven(url = "{uri-snapshot-repo}")
|
||||
endif::[]
|
||||
}
|
||||
----
|
||||
@@ -136,7 +136,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven { url "{uri-sonatype}" }
|
||||
maven { url "{uri-snapshot-repo}" }
|
||||
endif::[]
|
||||
}
|
||||
----
|
||||
@@ -160,7 +160,7 @@ ifndef::is-release-version[]
|
||||
<repository>
|
||||
<id>sonatype-s01</id>
|
||||
<name>Sonatype S01</name>
|
||||
<url>{uri-sonatype}</url>
|
||||
<url>{uri-snapshot-repo}</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
endif::[]
|
||||
|
||||
@@ -51,7 +51,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven(url = "{uri-sonatype}")
|
||||
maven(url = "{uri-snapshot-repo}")
|
||||
endif::[]
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ ifdef::is-release-version[]
|
||||
mavenCentral()
|
||||
endif::[]
|
||||
ifndef::is-release-version[]
|
||||
maven { url "{uri-sonatype}" }
|
||||
maven { url "{uri-snapshot-repo}" }
|
||||
endif::[]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,67 +1,495 @@
|
||||
= Pkl 0.32.0 Release Notes
|
||||
= Pkl 0.32 Release Notes
|
||||
:version: 0.32
|
||||
:version-minor: 0.32.0
|
||||
:release-date: TBD
|
||||
:release-date: July 8th, 2026
|
||||
:version-next: 0.33
|
||||
:version-next-date: TBD
|
||||
:version-next-date: October 2026
|
||||
|
||||
include::partial$intro.adoc[]
|
||||
|
||||
NOTE: This is the final release that distributes binaries for macOS/amd64.
|
||||
|
||||
== Highlights [small]#💖#
|
||||
|
||||
News you don't want to miss.
|
||||
=== New data type: `Reference`
|
||||
|
||||
.XXX
|
||||
[%collapsible]
|
||||
This release introduces a new data type called `Reference` (https://github.com/apple/pkl/pull/1354[#1354], https://github.com/apple/pkl/pull/1691[#1691], https://github.com/apple/pkl/pull/1692[#1692], https://github.com/apple/pkl/pull/1693[#1693], https://github.com/apple/pkl/pull/1695[#1695]).
|
||||
|
||||
WARNING: This API is experimental. We are looking for feedback, and will aim to make this ready for production use in the next release.
|
||||
|
||||
A reference represents something whose actual value is unknown to Pkl, but nevertheless its type is checked.
|
||||
The purpose of this data type is to improve how Pkl can be used to configure systems like GitHub Actions, Pulumi, Terraform, and more.
|
||||
|
||||
For example, let's assume that some system accepts YAML configuration that looks like so:
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
taskA:
|
||||
uses: some-task
|
||||
|
||||
taskB:
|
||||
uses: some-other-task
|
||||
input: '${ taskA.output.number }'
|
||||
----
|
||||
|
||||
In terms of YAML, `'${ taskA.output.number }'` is just a string.
|
||||
However, semantically, it is an _expression_ in this target system, where `taskA.output.number` conveys some type.
|
||||
|
||||
Today, the only way to treat these values in Pkl is to also describe these as strings.
|
||||
This introduces many shortcomings:
|
||||
|
||||
1. It leaves users vulnerable to syntax errors in this system.
|
||||
2. It's hard to validate these beyond that they are a string.
|
||||
3. Pkl has no understanding of the relationship between `taskA` and `taskB`.
|
||||
|
||||
With references, the above can be modeled in Pkl also as plain lookups:
|
||||
|
||||
[source,pkl]
|
||||
----
|
||||
taskA {
|
||||
uses = "some-task"
|
||||
}
|
||||
|
||||
taskB {
|
||||
name = "some-other-task"
|
||||
input = taskA.output.number
|
||||
}
|
||||
----
|
||||
|
||||
Library authors describe types as `ref.Reference<D, T>`, where `D` is the _domain_, and `T` is the _referent type_.
|
||||
|
||||
[source,pkl]
|
||||
----
|
||||
import "pkl:ref"
|
||||
|
||||
class MyDomain extends ref.Domain { // <1>
|
||||
function renderReference(ref: ref.Reference<MyDomain, Any>): String =
|
||||
"${ " + ref.getData() + "." + ref.getPath().join(".") + " }"
|
||||
}
|
||||
|
||||
typealias MyReference<T> = ref.Reference<MyDomain, T> // <2>
|
||||
|
||||
class MyTask {
|
||||
input: MyReference<Number>
|
||||
}
|
||||
----
|
||||
<1> References exist inside a domain. The domain defines how these references should be stringified.
|
||||
<2> A typealias can be used to improve ergonomics when declaring references that share the same domain.
|
||||
|
||||
Pkl will check that type arguments match up:
|
||||
|
||||
* The referent type must line up.
|
||||
+
|
||||
`MyReference<Int>` is not assignable to `MyReference<String>`.
|
||||
* The domain must line up.
|
||||
+
|
||||
`ref.Reference<MyDomain, Int>` is not assignable to `ref.Reference<OtherDomain, Int>`.
|
||||
|
||||
Additionally, references give you synthetic members.
|
||||
|
||||
[source,pkl]
|
||||
----
|
||||
class Bird {
|
||||
name: String
|
||||
}
|
||||
|
||||
bird: MyReference<Bird>
|
||||
|
||||
birdName = bird.name // <1>
|
||||
----
|
||||
<1> Gives a `MyReference<String>`, because `class Bird` has property `name: String`
|
||||
|
||||
The synthetic member contains metadata about the path that was used to access it (`.name` in this
|
||||
case).
|
||||
This can be used to stringify this reference in that target domain.
|
||||
|
||||
To read more about references, consult the xref:language-reference:index.adoc#references[language reference].
|
||||
To read through the design decisions made, consult the https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0020-type-safe-deferred-references.adoc[SPICE].
|
||||
|
||||
=== Custom HTTP Headers
|
||||
|
||||
Pkl can now attach custom HTTP headers to outbound requests, making it possible to access private or authenticated resources (https://github.com/apple/pkl/pull/1196[#1196], https://github.com/apple/pkl/pull/1584[#1584]).
|
||||
|
||||
For example, a CLI user can add an `Authorization` header either in settings.pkl, or the PklProject file:
|
||||
|
||||
[tabs]
|
||||
====
|
||||
XXX
|
||||
~/.pkl/settings.pkl::
|
||||
+
|
||||
[source,pkl]
|
||||
----
|
||||
amends "pkl:settings"
|
||||
|
||||
http {
|
||||
headers {
|
||||
["https://my.private.server/**"] {
|
||||
["Authorization"] = "Bearer my-secret-token"
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
PklProject::
|
||||
+
|
||||
[source,pkl]
|
||||
----
|
||||
amends "pkl:Project"
|
||||
|
||||
evaluatorSettings {
|
||||
http {
|
||||
headers {
|
||||
["https://my.private.server/**"] {
|
||||
["Authorization"] = "Bearer my-secret-token"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Each key in `headers` is a glob pattern matched against the request URL.
|
||||
When a request is made, every matching pattern's headers are added to the request.
|
||||
|
||||
Headers can also be configured in other ways:
|
||||
|
||||
* In the pkl-gradle plugin
|
||||
* As a CLI flag
|
||||
* In the Java/Swift/Go/Kotlin evaluator APIs
|
||||
* In the pkl-executor API
|
||||
|
||||
Header names must conform to RFC 7230 token syntax.
|
||||
Certain reserved names (e.g. `host`, `connection`, `content-length`) and prefixes (`proxy-`, `sec-`) are forbidden.
|
||||
|
||||
Thank you to https://github.com/kyokuping[@kyokuping] for their contributions to this feature!
|
||||
|
||||
To learn more, consult https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0022-http-headers.adoc[SPICE-0022].
|
||||
|
||||
== Noteworthy [small]#🎶#
|
||||
|
||||
Ready when you need them.
|
||||
=== Resolved evaluator settings
|
||||
|
||||
PklProject files now resolve evaluator settings that are file paths (https://github.com/apple/pkl/pull/1394[#1394]).
|
||||
|
||||
Some of the settings within `pkl:EvaluatorSettings` represent file paths.
|
||||
However, these paths are resolved inconsistently:
|
||||
|
||||
* Pkl is inconsistent about what relative paths mean. `rootDir`, `moduleCacheDir`, and `modulePath` are relative to the project dir, while `ExternalReader.executable` is relative to the PWD.
|
||||
* External readers defined in a PklProject have different behavior depending on the PWD.
|
||||
* The logic for resolving these paths is dependent on the caller, rather than Pkl.
|
||||
|
||||
For CLI users, this means that the current working directory can affect how evaluator settings are loaded.
|
||||
|
||||
In Pkl 0.32, these paths are resolved entirely within Pkl, and resolved against the enclosing directory.
|
||||
|
||||
A new method `resolve()` is added to `pkl:EvaluatorSettings`, and a new property `resolvedEvaluatorSettings` is added to `pkl:Project`.
|
||||
Language bindings are expected to use `resolvedEvaluatorSettings` when configuring the evaluator.
|
||||
|
||||
To read more about this change, consult https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0027-resolved-paths-in-pkl-evaluatorsettings.adoc[SPICE-0027].
|
||||
|
||||
=== Line continuations in multiline strings
|
||||
|
||||
When authoring multiline strings, it is now possible to use a _line continuation_ to break a single line's value over multiple lines (https://github.com/apple/pkl/pull/1507[#1507], https://github.com/apple/pkl/pull/1564[#1564]).
|
||||
|
||||
These two string snippets are logically identical:
|
||||
|
||||
[source,pkl]
|
||||
----
|
||||
str =
|
||||
"""
|
||||
Although the Dodo is extinct, \
|
||||
the species will be remembered.
|
||||
"""
|
||||
----
|
||||
|
||||
[source%parsed,pkl]
|
||||
----
|
||||
str = "Although the Dodo is extinct, the species will be remembered."
|
||||
----
|
||||
|
||||
To read more about this design, consult https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0028-multiline-string-continuation.adoc[SPICE-0028].
|
||||
|
||||
[[parse-time-variable-resolution]]
|
||||
=== Parse-time variable resolution
|
||||
|
||||
Pkl now resolves variables at parse time (https://github.com/apple/pkl/pull/1429[#1429], https://github.com/apple/pkl/pull/1622[#1622], https://github.com/apple/pkl/pull/1634[#1634], https://github.com/apple/pkl/pull/1706[#1706]).
|
||||
|
||||
Currently, Pkl defers the resolution of variable names to when the node is executed.
|
||||
In Pkl 0.32, these are resolved when the file is parsed.
|
||||
|
||||
This is a pre-requisite feature for many upcoming features, such as flat member syntax and method varargs.
|
||||
|
||||
Additionally, this enables some runtime optimizations, including let expressions.
|
||||
|
||||
[[let-expression-improvements]]
|
||||
=== Let expression performance improvements
|
||||
|
||||
Performance improvements were made to the handling of xref:language-reference:index.adoc#let-expressions[let expressions] (https://github.com/apple/pkl/pull/1622[#1622], https://github.com/apple/pkl/pull/1634[#1634]).
|
||||
|
||||
Here is a sample benchmark:
|
||||
|
||||
[source,pkl]
|
||||
----
|
||||
amends "pkl:Benchmark"
|
||||
|
||||
microbenchmarks {
|
||||
["let"] {
|
||||
expression =
|
||||
let (a = 1)
|
||||
let (b = 2)
|
||||
let (c = 3)
|
||||
let (d = 4)
|
||||
let (e = 1)
|
||||
let (f = 2)
|
||||
let (g = 3)
|
||||
let (h = 4)
|
||||
let (i = 1)
|
||||
let (j = 2)
|
||||
let (k = 3)
|
||||
let (l = 4)
|
||||
let (m = 1)
|
||||
let (n = 2)
|
||||
let (o = 3)
|
||||
let (p = 4)
|
||||
let (q = 1)
|
||||
let (r = 2)
|
||||
let (s = 3)
|
||||
let (t = 4)
|
||||
a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s + t
|
||||
}
|
||||
}
|
||||
|
||||
output {
|
||||
renderer {
|
||||
converters {
|
||||
[Duration] = (it: Duration) -> super[Duration].apply(it.toUnit("ns"))
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
And here are the results when run on a MacBook Pro M4 Max machine: `jpkl` is about 12x faster, while native `pkl` is about 4000x faster:
|
||||
|
||||
|===
|
||||
|Variant |Results (mean)
|
||||
|
||||
|jpkl
|
||||
|1208.06.ns -> 97.76.ns
|
||||
|
||||
|pkl
|
||||
|1275.96.ns -> 0.32.ns
|
||||
|===
|
||||
|
||||
=== Test reporter
|
||||
|
||||
A test reporter option is added when running tests (https://github.com/apple/pkl/pull/1563[#1563], https://github.com/apple/pkl/pull/1597[#1597]).
|
||||
|
||||
A new CLI flag, `--test-reporter`, is now available to the `pkl test` and `pkl project package` commands.
|
||||
This flag accepts the name of a test reporter to be used to format test result output.
|
||||
|
||||
There are two possible reporters:
|
||||
|
||||
* `spec` (default) - the current reporter
|
||||
* `minimal` - a reporter that only emits failing tests
|
||||
|
||||
This option is also available to pkl-gradle users.
|
||||
|
||||
=== Dependency notation improvements
|
||||
|
||||
Pkl's evaluator now accepts https://pkl-lang.org/main/current/language-reference/index.html#dependency-notation[dependency notation URIs] as source modules (https://github.com/apple/pkl/pull/1595[#1595]).
|
||||
|
||||
In Pkl 0.31, we introduced xref:0.31.adoc#cli-dependency-notation[CLI support for dependency notation].
|
||||
Now, this support has been extended to the evaluator itself.
|
||||
This means that users of Pkl's various language bindings can also use dependency notation.
|
||||
|
||||
Additionally, the limitation on local dependencies has been dropped.
|
||||
|
||||
=== pkldoc supports single-package docsites
|
||||
|
||||
pkldoc has improved support for single-package documentation websites (https://github.com/apple/pkl/pull/1592[#1592]).
|
||||
|
||||
When a docsite has only one package name, and also no overview from a `docsite-info.pkl`, the resulting docsite does not have a top-level package index page.
|
||||
Instead, it redirects to the package page, and omits the site-level element from the breadcrumb.
|
||||
|
||||
=== Allowed package imports in `PklProject`
|
||||
|
||||
PklProject files can now import xref:language-reference:index.adoc#package-asset-uri[package asset URIs] (https://github.com/apple/pkl/pull/1547[#1547]).
|
||||
|
||||
This means that it is now possible to centralize and share common configurations across multiple projects.
|
||||
|
||||
=== Java Library Changes
|
||||
|
||||
==== Switch to JSpecify annotations
|
||||
|
||||
Pkl has switched to using https://jspecify.dev[JSpecify] for annotating nullability (https://github.com/apple/pkl/pull/1515[#1515], https://github.com/apple/pkl/pull/1527[#1527], https://github.com/apple/pkl/pull/1528[#1528], https://github.com/apple/pkl/pull/1530[#1530], https://github.com/apple/pkl/pull/1544[#1544], https://github.com/apple/pkl/pull/1601[#1601], https://github.com/apple/pkl/pull/1607[#1607]).
|
||||
|
||||
Currently, Pkl uses annotations from the `com.google.code.findbugs:jsr305` library.
|
||||
This suffers from some issues:
|
||||
|
||||
* The https://jcp.org/en/jsr/detail?id=305[JSR-305 proposal] itself is dormant and unlikely to be adopted.
|
||||
* The `com.google.code.findbugs:jsr305` library contributes packages to `javax`, which violates the https://www.oracle.com/downloads/licenses/binary-code-license.html[Oracle Binary Code License Agreement].
|
||||
|
||||
In contrast, JSpecify is widely seen as the standard for nullability annotations, and is already understood by most tools.
|
||||
|
||||
This impacts Pkl's Java APIs; methods previously annotated using JSR-305 nullability annotations now use JSpecify.
|
||||
Additionally, the Java code generator now emits JSpecify annotations by default.
|
||||
|
||||
==== New API: `org.pkl.config.java.ConfigDecoder`
|
||||
|
||||
A new API is introduced called `org.pkl.config.java.ConfigDecoder` (https://github.com/apple/pkl/pull/1533[#1533]).
|
||||
|
||||
Currently, the `org.pkl.config.java.Config` interface mixes configuration representation with decoding logic.
|
||||
To better separate these concerns, a new API is introduced for decoding.
|
||||
|
||||
Example:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
class Main {
|
||||
Config getConfig() {
|
||||
var decoder = new ConfigDecoderBuilder().preconfigured().build();
|
||||
return decoder.decode(bytes);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
==== New `asNullable` methods in `pkl.config.java`
|
||||
|
||||
New methods are added for decoding into nullable types (https://github.com/apple/pkl/pull/1544[#1544]).
|
||||
|
||||
The following methods are introduced:
|
||||
|
||||
* `org.pkl.config.java.Config.asNullable`
|
||||
* `org.pkl.config.java.JavaType.pairOfNullableFirst`
|
||||
* `org.pkl.config.java.JavaType.pairOfNullableSecond`
|
||||
* `org.pkl.config.java.JavaType.pairOfNullableFirstAndSecond`
|
||||
* `org.pkl.config.java.JavaType.arrayOfNullable`
|
||||
* `org.pkl.config.java.JavaType.iterableOfNullable`
|
||||
* `org.pkl.config.java.JavaType.collectionOfNullable`
|
||||
* `org.pkl.config.java.JavaType.listOfNullable`
|
||||
* `org.pkl.config.java.JavaType.setOfNullable`
|
||||
* `org.pkl.config.java.JavaType.mapOfNullableKeys`
|
||||
* `org.pkl.config.java.JavaType.mapOfNullableValues`
|
||||
* `org.pkl.config.java.JavaType.mapOfNullableKeysAndValues`
|
||||
|
||||
NOTE: `org.pkl.config.java.Config.as` can also return a `null` value. In a future release, this method will have a runtime non-null assertion.
|
||||
|
||||
==== `pkl-formatter` migrated to Java
|
||||
|
||||
The `pkl-formatter` library has been migrated from Kotlin to Java (https://github.com/apple/pkl/pull/1514[#1514]).
|
||||
|
||||
Therefore, its Kotlin dependency is dropped.
|
||||
|
||||
=== Standard Library Changes
|
||||
|
||||
==== `pkl:EvaluatorSettings`
|
||||
|
||||
**Additions**
|
||||
|
||||
* New method: link:{uri-stdlib-evaluatorSettingsModule}#resolve()[`EvaluatorSettings.resolve()`]
|
||||
* New method: link:{uri-stdlib-evaluatorSettingsModule}#resolveForOs()[`EvaluatorSettings.resolveForOs()`]
|
||||
* New property: link:{uri-stdlib-evaluatorSettingsExternalReaderClass}#workingDir[`EvaluatorSettings#ExternalReader.workingDir`]
|
||||
* New property: link:{uri-stdlib-evaluatorSettingsHttpClass}#headers[`EvaluatorSettings#Http.headers`]
|
||||
* New typealias: link:{uri-stdlib-evaluatorSettingsModule}#HttpHeaders[`EvaluatorSettings.HttpHeaders`]
|
||||
* New typealias: link:{uri-stdlib-evaluatorSettingsModule}#HttpHeaderName[`EvaluatorSettings.HttpHeaderName`]
|
||||
* New typealias: link:{uri-stdlib-evaluatorSettingsModule}#HttpHeaderValue[`EvaluatorSettings.HttpHeaderValue`]
|
||||
|
||||
==== `pkl:base`
|
||||
|
||||
* New property: link:{uri-stdlib-baseModule}/String#isGlobPattern[`String.isGlobPattern`]
|
||||
|
||||
==== `pkl:Project`
|
||||
|
||||
**Additions**
|
||||
|
||||
* New property: link:{uri-stdlib-projectModule}#resolvedEvaluatorSettings[`Project.resolvedEvaluatorSettings`]
|
||||
|
||||
==== `pkl:ref`
|
||||
|
||||
* New module introduced.
|
||||
|
||||
=== pkl-gradle changes
|
||||
|
||||
The following changes have been made to pkl-gradle.
|
||||
|
||||
==== Support for external readers
|
||||
|
||||
External readers can now be configured when configuring evaluators (https://github.com/apple/pkl/pull/1578[#1578]).
|
||||
|
||||
For example:
|
||||
|
||||
[source,kotlin]
|
||||
----
|
||||
val myPklTask by pkl.evaluators.creating {
|
||||
val foo by externalModuleReaders.creating {
|
||||
executable = "pkl-foo-reader"
|
||||
arguments = listOf("--bar", "baz")
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
==== Support for module/resource readers from SPI
|
||||
|
||||
Gradle users can now add module/resource readers by registering a service via the Java SPI mechanism (https://github.com/apple/pkl/pull/1581[#1581]).
|
||||
|
||||
==== Support for Gradle configuration cache
|
||||
|
||||
The plugin now supports the Gradle configuration cache feature (https://github.com/apple/pkl/issues/1425[#1425]).
|
||||
|
||||
Thanks to https://github.com/ffluk3[@ffluk3] for their contributions to this feature!
|
||||
|
||||
== Breaking Changes [small]#💔#
|
||||
|
||||
Things to watch out for when upgrading.
|
||||
=== Name resolution changes
|
||||
|
||||
Variables are now <<parse-time-variable-resolution,resolved at parse time>>.
|
||||
|
||||
As part of this change, some names are resolved differently.
|
||||
|
||||
Take the following code:
|
||||
|
||||
[source,pkl]
|
||||
----
|
||||
qux = "outer"
|
||||
|
||||
foo {
|
||||
when (cond) {
|
||||
qux = "inner"
|
||||
}
|
||||
res = qux
|
||||
}
|
||||
----
|
||||
|
||||
Currently, `res = qux` will eval to either `res = "outer"` or `res = "inner"` depending on whether `cond` evals to `true` or not.
|
||||
This is a lexical lookup that is either one level up, or zero levels up, depending on the result of code execution.
|
||||
|
||||
This type of resolution is not possible at parse time, because we do not know what `cond` executes to.
|
||||
In Pkl 0.32, `res` will always resolve to the inner `qux`, and this snippet will throw if the when generator does not fire.
|
||||
|
||||
=== Java API changes
|
||||
|
||||
Changes have been made to the Java API.
|
||||
The following breaking changes have been made to the Java API.
|
||||
|
||||
==== Removals and deprecations
|
||||
* `org.pkl.config.java.Config#makeConfig`
|
||||
+
|
||||
Removed without replacement
|
||||
|
||||
The following APIs have been removed without replacement.
|
||||
* `org.pkl.config.java.Config.fromPklBinary`
|
||||
+
|
||||
Deprecated, replaced with `org.pkl.config.java.ConfigDecoder`
|
||||
|
||||
* `org.pkl.config.java.Config#makeConfig` (pr:https://github.com/apple/pkl/pull/1531[])
|
||||
* `org.pkl.config.java.mapper.NonNull`
|
||||
+
|
||||
Deprecated, replaced with `org.jspecify.annotations.NonNull`
|
||||
|
||||
The following APIs have been deprecated for removal.
|
||||
* `org.pkl.core.evaluatorSettings.PklEvaluatorSettings.parse`
|
||||
+
|
||||
No longer accepts `pathNormalizer` argument
|
||||
|
||||
* `org.pkl.config.java.mapper.NonNull` (https://github.com/apple/pkl/pull/1607[#1607]).
|
||||
|
||||
==== Changes
|
||||
|
||||
* `org.pkl.core.evaluatorSettings.PklEvaluatorSettings.parse` no longer accepts a `pathNormalizer` argument.
|
||||
* `org.pkl.formatter.Formatter`
|
||||
** Pass `GrammarVersion` to constructor instead of each `format` method
|
||||
** Replace `format(Path): String` with `format(Reader, Appendable)`
|
||||
** Mark as `throws IOException`
|
||||
** Deprecate methods that accept `GrammarVersion` as an argument
|
||||
|
||||
=== Loading rule changes in `pkl:EvaluatorSettings`
|
||||
|
||||
Breaking changes have been made to how evaluator settings are loaded (https://github.com/apple/pkl/pull/1394[#1394]).
|
||||
Breaking changes have been made to how evaluator settings are loaded when using `PklProject` (https://github.com/apple/pkl/pull/1394[#1394]).
|
||||
|
||||
==== Loading rule changes for the external reader executable
|
||||
|
||||
@@ -76,18 +504,68 @@ The `--external-module-reader` and `--external-resource-reader` CLI flags will _
|
||||
|
||||
This makes this behavior consistent with how other settings work.
|
||||
|
||||
== Work In Progress [small]#🚆#
|
||||
== Bug Fixes [small]#🐜#
|
||||
|
||||
They missed the train but deserve a mention.
|
||||
The following bugs have been fixed.
|
||||
|
||||
.XXX
|
||||
[%collapsible]
|
||||
====
|
||||
XXX
|
||||
====
|
||||
* Data race in MessagePack encoder during concurrent server sends (https://github.com/apple/pkl/issues/1486[#1486])
|
||||
* pkl-doc library publishes incorrect Maven dependency scopes (https://github.com/apple/pkl/issues/1517[#1517])
|
||||
* Re-using pklbinary#Renderer during rendering results in incorrect output (https://github.com/apple/pkl/pull/1525[#1525])
|
||||
* Cannot glob using subpatterns inside a project dependency (https://github.com/apple/pkl/issues/1545[#1545])
|
||||
* Project package command incompatible with glob imports on Windows (https://github.com/apple/pkl/issues/1556[#1556])
|
||||
* Thrown PklBugException when using power assertions with unavailable source sections (https://github.com/apple/pkl/pull/1571[#1571])
|
||||
* pkl-doc: DocGenerator never shuts down its thread pool (https://github.com/apple/pkl/issues/1583[#1583])
|
||||
* Imports gathering Gradle task can fail with a confusing exception (https://github.com/apple/pkl/issues/1591[#1591])
|
||||
* HTTP rewrite fails with PklBugException under tr-TR locale when host contains 'I' (https://github.com/apple/pkl/issues/1617[#1617])
|
||||
* Formatter bug fixes (https://github.com/apple/pkl/pull/1619[#1619])
|
||||
* Unrelated error message thrown when computing an error message (https://github.com/apple/pkl/pull/1629[#1629])
|
||||
* pkl-binary serialization produces an incomplete msgpack value in the presence of local properties (https://github.com/apple/pkl/issues/1631[#1631]).
|
||||
* Poor parser error message (https://github.com/apple/pkl/issues/1638[#1638])
|
||||
* relativePathTo does not check if receiver is a module (https://github.com/apple/pkl/issues/1649[#1649])
|
||||
* `Int` overflow on multiplication throws unexpected exception (https://github.com/apple/pkl/issues/1651[#1651])
|
||||
* Incorrect eager check for `Map` type (https://github.com/apple/pkl/issues/1653[#1653])
|
||||
* Incorrect `toRadixString()` for `math.minInt` (https://github.com/apple/pkl/issues/1655[#1655])
|
||||
* `Evaluator.evaluateSchema()` throws if properties are annotated with `@ConvertProperty` (https://github.com/apple/pkl/issues/1657[#1657])
|
||||
* `String.padStart` and `String.padEnd` return incorrect strings sometimes (https://github.com/apple/pkl/issues/1661[#1661])
|
||||
* `String.getOrNull` crashes with certain strings (https://github.com/apple/pkl/issues/1662[#1662])
|
||||
* Incorrect facts in `pkl:base` doc comments (https://github.com/apple/pkl/pull/1669[#1669])
|
||||
* Index-based methods on Set aren't implemented (https://github.com/apple/pkl/issues/1682[#1682])
|
||||
* pkl-gradle throws exception when a Pkl task can't create an evaluator during configuration time (https://github.com/apple/pkl/pull/1684[#1684])
|
||||
* Unrelated exception gets thrown when validating elements/entries in objects (https://github.com/apple/pkl/issues/1697[#1697])
|
||||
* Type argument is lost in constraint expressions within generic typealiases (https://github.com/apple/pkl/issues/1705[#1705])
|
||||
* Typealiases with type var as root are broken (https://github.com/apple/pkl/issues/1711[#1711])
|
||||
* Incorrect `List`/`Set`/`Map`/`Listing`/`Mapping`/union type check behavior through typealiases (https://github.com/apple/pkl/issues/1710[#1710])
|
||||
* Type aliases with type var as root are broken (https://github.com/apple/pkl/issues/1711[#1711])
|
||||
* Type checks through aliases are always run lazily even when they should be eager (https://github.com/apple/pkl/issues/1716[#1716])
|
||||
* Improve thread safety when evaluating `pkl:base` (https://github.com/apple/pkl/pull/1719[#1719])
|
||||
* Incorrect member links in doc comments (https://github.com/apple/pkl/pull/1723[#1723])
|
||||
* pkl-gradle plugin does not allow `projectpackage:` reads by default (https://github.com/apple/pkl/issues/1734[#1734])
|
||||
* `IntSeq` incorrectly emits on empty ``IntSeq``s (https://github.com/apple/pkl/issues/1738[#1738])
|
||||
|
||||
== Security Fixes [small]#🔒#
|
||||
|
||||
The following security vulnerabilities were fixed:
|
||||
|
||||
* Remote packages can read local filesystem items by escaping local dependency roots (https://github.com/apple/pkl/security/advisories/GHSA-fgvf-hh2w-cxff[GHSA-fgvf-hh2w-cxff], https://github.com/apple/pkl/pull/1737[#1737])
|
||||
* Packages can be read/written outside the configured cache directory (https://github.com/apple/pkl/security/advisories/GHSA-87qh-25w9-mh34[GHSA-87qh-25w9-mh34], https://github.com/apple/pkl/pull/1683[#1683])
|
||||
|
||||
== Contributors [small]#🙏#
|
||||
|
||||
We would like to thank the contributors to this release (in alphabetical order):
|
||||
|
||||
* XXX
|
||||
* https://github.com/04cb[@04cb]
|
||||
* https://github.com/0xmrma[@0xmrma]
|
||||
* https://github.com/adityabagchi24[@adityabagchi24]
|
||||
* https://github.com/adityasingh2400[@adityasingh2400]
|
||||
* https://github.com/bioball[@bioball]
|
||||
* https://github.com/fallintoplace[@fallintoplace]
|
||||
* https://github.com/ffluk3[@ffluk3]
|
||||
* https://github.com/HT154[@HT154]
|
||||
* https://github.com/KushalP[@KushalP]
|
||||
* https://github.com/kyokuping[@kyokuping]
|
||||
* https://github.com/ldaley[@ldaley]
|
||||
* https://github.com/mirkoalicastro[@mirkoalicastro]
|
||||
* https://github.com/netvl[@netvl]
|
||||
* https://github.com/odenix[@odenix]
|
||||
* https://github.com/stackoverflow[@stackoverflow]
|
||||
* https://github.com/vinayakj592[@vinayakj592]
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
= Pkl 0.33 Release Notes
|
||||
:version: 0.33
|
||||
:version-minor: 0.33.0
|
||||
:release-date: XXX
|
||||
:version-next: 0.34
|
||||
:version-next-date: February 2027
|
||||
|
||||
include::partial$intro.adoc[]
|
||||
|
||||
== Highlights [small]#💖#
|
||||
|
||||
=== XXX
|
||||
|
||||
== Noteworthy [small]#🎶#
|
||||
|
||||
=== XXX
|
||||
|
||||
== Breaking Changes [small]#💔#
|
||||
|
||||
=== XXX
|
||||
|
||||
== Bug Fixes [small]#🐜#
|
||||
|
||||
* XXX
|
||||
|
||||
== Contributors [small]#🙏#
|
||||
|
||||
We would like to thank the contributors to this release (in alphabetical order):
|
||||
|
||||
* XXX
|
||||
@@ -1,8 +1,15 @@
|
||||
= Changelog
|
||||
include::ROOT:partial$component-attributes.adoc[]
|
||||
|
||||
[[release-0.33.0]]
|
||||
== 0.33.0 (UNRELEASED)
|
||||
|
||||
xref:0.33.adoc[Release Notes]
|
||||
|
||||
[[release-0.32.0]]
|
||||
== 0.32.0 (UNRELEASED)
|
||||
== 0.32.0 (2026-07-08)
|
||||
|
||||
xref:0.32.adoc[Release Notes]
|
||||
|
||||
[[release-0.31.1]]
|
||||
== 0.31.1 (2026-03-26)
|
||||
@@ -38,6 +45,7 @@ Thank you to all the contributors for this release!
|
||||
== 0.31.0 (2026-02-26)
|
||||
|
||||
xref:0.31.adoc[Release Notes]
|
||||
|
||||
[[release-0.30.2]]
|
||||
|
||||
== 0.30.2 (2025-12-15)
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
* xref:ROOT:evolution-and-roadmap.adoc[Evolution and Roadmap]
|
||||
|
||||
* xref:release-notes:index.adoc[Release Notes]
|
||||
** xref:release-notes:0.33.adoc[0.33 Release Notes]
|
||||
** xref:release-notes:0.32.adoc[0.32 Release Notes]
|
||||
** xref:release-notes:0.31.adoc[0.31 Release Notes]
|
||||
** xref:release-notes:0.30.adoc[0.30 Release Notes]
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
# suppress inspection "UnusedProperty" for whole file
|
||||
|
||||
group=org.pkl-lang
|
||||
version=0.32.0
|
||||
version=0.33.0
|
||||
|
||||
# google-java-format requires jdk.compiler exports
|
||||
org.gradle.jvmargs= \
|
||||
|
||||
@@ -3,9 +3,9 @@ assertj = "3.27.7"
|
||||
checksumPlugin = "1.4.0"
|
||||
# 5.0.3 is the last version compatible with Kotlin 2.2
|
||||
clikt = "5.0.3"
|
||||
commonMark = "0.28.0"
|
||||
commonMark = "0.29.0"
|
||||
downloadTaskPlugin = "5.7.0"
|
||||
errorProne = "2.49.0"
|
||||
errorProne = "2.50.0"
|
||||
errorPronePlugin = "5.1.0"
|
||||
geantyref = "2.0.1"
|
||||
#noinspection UnusedVersionCatalogEntry
|
||||
@@ -32,7 +32,7 @@ ideaExtPlugin = "1.4.1"
|
||||
javaPoet = "0.16.0"
|
||||
javaxInject = "1"
|
||||
jimfs = "1.3.1"
|
||||
jline = "4.1.3"
|
||||
jline = "4.2.1"
|
||||
jmh = "1.37"
|
||||
jmhPlugin = "0.7.3"
|
||||
jspecify = "1.0.0"
|
||||
@@ -54,14 +54,14 @@ ktfmt = "0.62"
|
||||
log4j = "2.17.1"
|
||||
msgpack = "0.9.12"
|
||||
nexusPublishPlugin = "2.0.0"
|
||||
nullaway = "0.13.4"
|
||||
nullaway = "0.13.7"
|
||||
nullawayPlugin = "3.0.0"
|
||||
nuValidator = "26.5.29"
|
||||
nuValidator = "26.6.24"
|
||||
paguro = "3.10.3"
|
||||
shadowPlugin = "9.4.2"
|
||||
slf4j = "2.0.18"
|
||||
snakeYaml = "3.0.1"
|
||||
spotlessPlugin = "8.6.0"
|
||||
spotlessPlugin = "8.7.0"
|
||||
wiremock = "3.13.2"
|
||||
|
||||
[libraries] # ordered alphabetically
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=bafc141b619ad6350fd975fc903156dd5c151998cc8b058e8c1044ab5f7b031f
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
|
||||
distributionSha256Sum=bbaeb2fef8710818cf0e261201dab964c572f92b942812df0c3620d62a529a01
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip
|
||||
networkTimeout=10000
|
||||
retries=0
|
||||
retryBackOffMs=500
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
# gradlew start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
@@ -29,7 +29,7 @@
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
# ksh gradlew
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
|
||||
Vendored
+2
-2
@@ -19,7 +19,7 @@
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem gradlew startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@@ -72,7 +72,7 @@ echo location of your Java installation. 1>&2
|
||||
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
@rem Execute gradlew
|
||||
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||
@rem which allows us to clear the local environment before executing the java command
|
||||
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
|
||||
|
||||
+3
-3
@@ -2,15 +2,15 @@
|
||||
"catalogs": {},
|
||||
"aliases": {
|
||||
"pkl": {
|
||||
"script-ref": "org.pkl-lang:pkl-cli-java:0.31.1",
|
||||
"script-ref": "org.pkl-lang:pkl-cli-java:0.32.0",
|
||||
"java-agents": []
|
||||
},
|
||||
"pkl-codegen-java": {
|
||||
"script-ref": "org.pkl-lang:pkl-codegen-java:0.31.1",
|
||||
"script-ref": "org.pkl-lang:pkl-codegen-java:0.32.0",
|
||||
"java-agents": []
|
||||
},
|
||||
"pkl-codegen-kotlin": {
|
||||
"script-ref": "org.pkl-lang:pkl-codegen-kotlin:0.31.1",
|
||||
"script-ref": "org.pkl-lang:pkl-codegen-kotlin:0.32.0",
|
||||
"java-agents": []
|
||||
}
|
||||
},
|
||||
|
||||
@@ -83,8 +83,8 @@ tasks.shadowJar {
|
||||
exclude("module-info.*")
|
||||
}
|
||||
|
||||
val testJavaExecutable by
|
||||
tasks.registering(Test::class) {
|
||||
val testJavaExecutable =
|
||||
tasks.register<Test>("testJavaExecutable") {
|
||||
testClassesDirs = tasks.test.get().testClassesDirs
|
||||
classpath =
|
||||
// compiled test classes
|
||||
@@ -138,7 +138,7 @@ fun Exec.useRootDirAndSuppressOutput() {
|
||||
|
||||
// 0.28 Preparing for JDK21 toolchains revealed that `testStartJavaExecutable` may pass, even though
|
||||
// the evaluator fails. To catch this, we eval a simple expression using the fat jar.
|
||||
val testEvalJavaExecutable by
|
||||
val testEvalJavaExecutable =
|
||||
setupJavaExecutableRun("testEvalJavaExecutable", evalTestFlags) { useRootDirAndSuppressOutput() }
|
||||
|
||||
// Run the same evaluator tests on all configured JDK test versions.
|
||||
|
||||
@@ -19,10 +19,11 @@ plugins {
|
||||
id("pklPublishLibrary")
|
||||
}
|
||||
|
||||
val svmClasspath: Configuration by configurations.creating
|
||||
val svmClasspath: Configuration = configurations.create("svmClasspath")
|
||||
|
||||
// used by pklNativeExecutable.gradle.kts
|
||||
@Suppress("unused") val svm: SourceSet by sourceSets.creating { compileClasspath = svmClasspath }
|
||||
@Suppress("unused")
|
||||
val svm: SourceSet = sourceSets.create("svm") { compileClasspath = svmClasspath }
|
||||
|
||||
dependencies {
|
||||
api(projects.pklCore)
|
||||
|
||||
@@ -37,7 +37,7 @@ dependencies {
|
||||
* These packages are used by PackageServer to serve assets when running LanguageSnippetTests and
|
||||
* PackageResolversTest.
|
||||
*/
|
||||
val createTestPackages by tasks.registering
|
||||
val createTestPackages = tasks.register("createTestPackages")
|
||||
|
||||
// make sure that declaring a dependency on this project suffices to have test fixtures generated
|
||||
tasks.processResources {
|
||||
@@ -92,8 +92,8 @@ val keystoreName = "localhost.p12"
|
||||
val keystoreFile = keystoreDir.map { it.file(keystoreName) }
|
||||
val certsFileName = "localhost.pem"
|
||||
|
||||
val generateKeys by
|
||||
tasks.registering(JavaExec::class) {
|
||||
val generateKeys =
|
||||
tasks.register<JavaExec>("generateKeys") {
|
||||
outputs.file(keystoreFile)
|
||||
mainClass.set("sun.security.tools.keytool.Main")
|
||||
args =
|
||||
@@ -117,8 +117,8 @@ val generateKeys by
|
||||
}
|
||||
}
|
||||
|
||||
val exportCerts by
|
||||
tasks.registering(JavaExec::class) {
|
||||
val exportCerts =
|
||||
tasks.register<JavaExec>("exportCerts") {
|
||||
val outputFile = keystoreDir.map { it.file(certsFileName) }
|
||||
dependsOn(generateKeys)
|
||||
inputs.file(keystoreFile)
|
||||
|
||||
@@ -19,11 +19,11 @@ plugins {
|
||||
id("pklPublishLibrary")
|
||||
}
|
||||
|
||||
val pklConfigJava: Configuration by configurations.creating
|
||||
val pklConfigJava: Configuration = configurations.create("pklConfigJava")
|
||||
|
||||
val pklConfigJavaAll: Configuration by configurations.creating
|
||||
val pklConfigJavaAll: Configuration = configurations.create("pklConfigJavaAll")
|
||||
|
||||
val pklCodegenKotlin: Configuration by configurations.creating
|
||||
val pklCodegenKotlin: Configuration = configurations.create("pklCodegenKotlin")
|
||||
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
@@ -49,8 +49,8 @@ dependencies {
|
||||
testImplementation(libs.geantyref)
|
||||
}
|
||||
|
||||
val generateTestConfigClasses by
|
||||
tasks.registering(JavaExec::class) {
|
||||
val generateTestConfigClasses =
|
||||
tasks.register<JavaExec>("generateTestConfigClasses") {
|
||||
val outputDir = layout.buildDirectory.dir("testConfigClasses")
|
||||
outputs.dir(outputDir)
|
||||
inputs.dir("src/test/resources/codegenPkl")
|
||||
|
||||
@@ -35,9 +35,10 @@ val externalReaderFixtureSourceSet: NamedDomainObjectProvider<SourceSet> =
|
||||
runtimeClasspath += sourceSets.test.get().output + sourceSets.test.get().runtimeClasspath
|
||||
}
|
||||
|
||||
val externalReaderFixtureImplementation: Configuration by configurations.getting {
|
||||
val externalReaderFixtureImplementation: Configuration =
|
||||
configurations.getByName("externalReaderFixtureImplementation") {
|
||||
extendsFrom(configurations.testImplementation.get())
|
||||
}
|
||||
}
|
||||
|
||||
idea {
|
||||
module {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 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.
|
||||
@@ -69,11 +69,11 @@ public record ImportGraph(Map<URI, Set<Import>> imports, Map<URI, URI> resolvedI
|
||||
var value = entry.getValue();
|
||||
var set = new TreeSet<Import>();
|
||||
if (!(value instanceof JsArray array)) {
|
||||
throw new FormatException("array", value.getClass());
|
||||
throw new FormatException("array", value == null ? Void.class : value.getClass());
|
||||
}
|
||||
for (var elem : array) {
|
||||
if (!(elem instanceof JsObject importObj)) {
|
||||
throw new FormatException("object", elem.getClass());
|
||||
throw new FormatException("object", elem == null ? Void.class : elem.getClass());
|
||||
}
|
||||
set.add(parseImport(importObj));
|
||||
}
|
||||
@@ -98,7 +98,7 @@ public record ImportGraph(Map<URI, Set<Import>> imports, Map<URI, URI> resolvedI
|
||||
var key = new URI(entry.getKey());
|
||||
var value = entry.getValue();
|
||||
if (!(value instanceof String str)) {
|
||||
throw new FormatException("string", value.getClass());
|
||||
throw new FormatException("string", value == null ? Void.class : value.getClass());
|
||||
}
|
||||
var valueUri = new URI(str);
|
||||
ret.put(key, valueUri);
|
||||
|
||||
@@ -109,6 +109,8 @@ final class JsonRenderer implements ValueRenderer {
|
||||
"Values of type `Bytes` cannot be rendered as JSON. Value: %s", (Object) value));
|
||||
}
|
||||
|
||||
// Pair coming from the runtime can never admit null (in-language null is represented as PNull)
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
@Override
|
||||
public void visitPair(Pair<?, ?> value) {
|
||||
try {
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.pkl.core;
|
||||
import java.net.URI;
|
||||
import java.util.*;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
/** Describes the property, method and class members of a module. */
|
||||
public final class ModuleSchema {
|
||||
@@ -33,8 +32,8 @@ public final class ModuleSchema {
|
||||
private final Map<String, TypeAlias> typeAliases;
|
||||
private final Map<String, URI> imports;
|
||||
|
||||
@LateInit private Map<String, PClass> __allClasses;
|
||||
@LateInit private Map<String, TypeAlias> __allTypeAliases;
|
||||
private @Nullable Map<String, PClass> __allClasses;
|
||||
private @Nullable Map<String, TypeAlias> __allTypeAliases;
|
||||
|
||||
/** Constructs a {@code ModuleSchema} instance. */
|
||||
public ModuleSchema(
|
||||
|
||||
@@ -27,6 +27,7 @@ public final class PClass extends Member implements Value {
|
||||
private final List<TypeParameter> typeParameters;
|
||||
private final Map<String, Property> properties;
|
||||
private final Map<String, Method> methods;
|
||||
private final @Nullable PClass moduleClass;
|
||||
|
||||
private @Nullable PType supertype;
|
||||
private @Nullable PClass superclass;
|
||||
@@ -42,12 +43,14 @@ public final class PClass extends Member implements Value {
|
||||
PClassInfo<?> classInfo,
|
||||
List<TypeParameter> typeParameters,
|
||||
Map<String, Property> properties,
|
||||
Map<String, Method> methods) {
|
||||
Map<String, Method> methods,
|
||||
@Nullable PClass moduleClass) {
|
||||
super(docComment, sourceLocation, modifiers, annotations, classInfo.getSimpleName());
|
||||
this.classInfo = classInfo;
|
||||
this.typeParameters = typeParameters;
|
||||
this.properties = properties;
|
||||
this.methods = methods;
|
||||
this.moduleClass = moduleClass;
|
||||
}
|
||||
|
||||
public void initSupertype(PType supertype, PClass superclass) {
|
||||
@@ -57,7 +60,7 @@ public final class PClass extends Member implements Value {
|
||||
|
||||
/**
|
||||
* Returns the name of the module that this class is declared in. Note that a module name is not
|
||||
* guaranteed to be unique, especially if it not declared but inferred from the module URI.
|
||||
* guaranteed to be unique, especially if it is not declared but inferred from the module URI.
|
||||
*/
|
||||
public String getModuleName() {
|
||||
return classInfo.getModuleName();
|
||||
@@ -119,6 +122,11 @@ public final class PClass extends Member implements Value {
|
||||
return allMethods;
|
||||
}
|
||||
|
||||
/** Returns the class's containing module's class, or this class if it is a module class. */
|
||||
public PClass getModuleClass() {
|
||||
return moduleClass != null ? moduleClass : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ValueVisitor visitor) {
|
||||
visitor.visitClass(this);
|
||||
@@ -138,6 +146,10 @@ public final class PClass extends Member implements Value {
|
||||
return getDisplayName();
|
||||
}
|
||||
|
||||
public boolean isSubclassOf(PClass other) {
|
||||
return this == other || getSuperclass() != null && getSuperclass().isSubclassOf(other);
|
||||
}
|
||||
|
||||
public abstract static class ClassMember extends Member {
|
||||
@Serial private static final long serialVersionUID = 0L;
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ public final class PClassInfo<T> implements Serializable {
|
||||
public static final URI pklSemverUri = URI.create("pkl:semver");
|
||||
public static final URI pklSettingsUri = URI.create("pkl:settings");
|
||||
public static final URI pklProjectUri = URI.create("pkl:Project");
|
||||
public static final URI pklRefUri = URI.create("pkl:ref");
|
||||
|
||||
public static final PClassInfo<Void> Any = pklBaseClassInfo("Any", Void.class);
|
||||
public static final PClassInfo<PNull> Null = pklBaseClassInfo("Null", PNull.class);
|
||||
@@ -82,9 +83,11 @@ public final class PClassInfo<T> implements Serializable {
|
||||
public static final PClassInfo<PObject> Version =
|
||||
new PClassInfo<>("pkl.semver", "Version", PObject.class, pklSemverUri);
|
||||
public static final PClassInfo<PObject> Project =
|
||||
new PClassInfo<>("pkl.Project", "ModuleClass", PObject.class, pklProjectUri);
|
||||
new PClassInfo<>("pkl.Project", MODULE_CLASS_NAME, PObject.class, pklProjectUri);
|
||||
public static final PClassInfo<PObject> Settings =
|
||||
new PClassInfo<>("pkl.settings", "ModuleClass", PObject.class, pklSettingsUri);
|
||||
new PClassInfo<>("pkl.settings", MODULE_CLASS_NAME, PObject.class, pklSettingsUri);
|
||||
public static final PClassInfo<Reference> Reference =
|
||||
new PClassInfo<>("pkl.ref", "Reference", Reference.class, pklRefUri);
|
||||
|
||||
public static final PClassInfo<Object> Unavailable =
|
||||
new PClassInfo<>("unavailable", "unavailable", Object.class, URI.create("pkl:unavailable"));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 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.
|
||||
@@ -18,6 +18,7 @@ package org.pkl.core;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/** A Pkl type as used in type annotations. */
|
||||
public abstract class PType implements Serializable {
|
||||
@@ -27,18 +28,33 @@ public abstract class PType implements Serializable {
|
||||
public static final PType UNKNOWN =
|
||||
new PType() {
|
||||
@Serial private static final long serialVersionUID = 0L;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "unknown";
|
||||
}
|
||||
};
|
||||
|
||||
/** The bottom type. */
|
||||
public static final PType NOTHING =
|
||||
new PType() {
|
||||
@Serial private static final long serialVersionUID = 0L;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "nothing";
|
||||
}
|
||||
};
|
||||
|
||||
/** The type of the enclosing module. */
|
||||
public static final PType MODULE =
|
||||
new PType() {
|
||||
@Serial private static final long serialVersionUID = 0L;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "module";
|
||||
}
|
||||
};
|
||||
|
||||
private PType() {}
|
||||
@@ -59,6 +75,22 @@ public abstract class PType implements Serializable {
|
||||
public String getLiteral() {
|
||||
return literal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ValueFormatter.basic().formatStringValue(literal, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@org.jspecify.annotations.Nullable Object obj) {
|
||||
if (obj == this) return true;
|
||||
return obj instanceof StringLiteral that && literal.equals(that.literal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return literal.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Class extends PType {
|
||||
@@ -92,6 +124,31 @@ public abstract class PType implements Serializable {
|
||||
public List<PType> getTypeArguments() {
|
||||
return typeArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
var result = pClass.getDisplayName();
|
||||
if (!typeArguments.isEmpty()) {
|
||||
result +=
|
||||
"<"
|
||||
+ typeArguments.stream().map(Object::toString).collect(Collectors.joining(", "))
|
||||
+ ">";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@org.jspecify.annotations.Nullable Object obj) {
|
||||
if (obj == this) return true;
|
||||
return obj instanceof Class that
|
||||
&& pClass.equals(that.pClass)
|
||||
&& typeArguments.equals(that.typeArguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * pClass.hashCode() + typeArguments.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Nullable extends PType {
|
||||
@@ -106,6 +163,24 @@ public abstract class PType implements Serializable {
|
||||
public PType getBaseType() {
|
||||
return baseType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return baseType instanceof Function || baseType instanceof Union
|
||||
? "(" + baseType + ")?"
|
||||
: baseType + "?";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@org.jspecify.annotations.Nullable Object obj) {
|
||||
if (obj == this) return true;
|
||||
return obj instanceof Nullable that && baseType.equals(that.baseType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return baseType.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Constrained extends PType {
|
||||
@@ -126,6 +201,29 @@ public abstract class PType implements Serializable {
|
||||
public List<String> getConstraints() {
|
||||
return constraints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return (baseType instanceof Function || baseType instanceof Union
|
||||
? "(" + baseType + ")"
|
||||
: baseType)
|
||||
+ "("
|
||||
+ String.join(", ", constraints)
|
||||
+ ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@org.jspecify.annotations.Nullable Object obj) {
|
||||
if (obj == this) return true;
|
||||
return obj instanceof Constrained that
|
||||
&& baseType.equals(that.baseType)
|
||||
&& constraints.equals(that.constraints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * baseType.hashCode() + constraints.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Alias extends PType {
|
||||
@@ -161,6 +259,31 @@ public abstract class PType implements Serializable {
|
||||
public PType getAliasedType() {
|
||||
return aliasedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
var result = typeAlias.getDisplayName();
|
||||
if (!typeArguments.isEmpty()) {
|
||||
result +=
|
||||
"<"
|
||||
+ typeArguments.stream().map(Object::toString).collect(Collectors.joining(", "))
|
||||
+ ">";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@org.jspecify.annotations.Nullable Object obj) {
|
||||
if (obj == this) return true;
|
||||
return obj instanceof Alias that
|
||||
&& typeAlias.equals(that.typeAlias)
|
||||
&& typeArguments.equals(that.typeArguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * typeAlias.hashCode() + typeArguments.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Function extends PType {
|
||||
@@ -181,6 +304,27 @@ public abstract class PType implements Serializable {
|
||||
public PType getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "("
|
||||
+ parameterTypes.stream().map(Object::toString).collect(Collectors.joining(", "))
|
||||
+ ") -> "
|
||||
+ returnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@org.jspecify.annotations.Nullable Object obj) {
|
||||
if (obj == this) return true;
|
||||
return obj instanceof Function that
|
||||
&& parameterTypes.equals(that.parameterTypes)
|
||||
&& returnType.equals(that.returnType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * parameterTypes.hashCode() + returnType.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Union extends PType {
|
||||
@@ -195,6 +339,22 @@ public abstract class PType implements Serializable {
|
||||
public List<PType> getElementTypes() {
|
||||
return elementTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return elementTypes.stream().map(Object::toString).collect(Collectors.joining(" | "));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@org.jspecify.annotations.Nullable Object obj) {
|
||||
if (obj == this) return true;
|
||||
return obj instanceof Union that && elementTypes.equals(that.elementTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return elementTypes.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class TypeVariable extends PType {
|
||||
@@ -213,5 +373,21 @@ public abstract class PType implements Serializable {
|
||||
public TypeParameter getTypeParameter() {
|
||||
return typeParameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return typeParameter.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@org.jspecify.annotations.Nullable Object obj) {
|
||||
if (obj == this) return true;
|
||||
return obj instanceof TypeVariable that && typeParameter.equals(that.typeParameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return typeParameter.hashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 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.
|
||||
@@ -227,9 +227,7 @@ final class PcfRenderer implements ValueRenderer {
|
||||
write(currIndent);
|
||||
writeIdentifier(name);
|
||||
|
||||
if (value == null) { // unevaluated property
|
||||
write(" = ?");
|
||||
} else if (value instanceof Composite) {
|
||||
if (value instanceof Composite) {
|
||||
write(' ');
|
||||
visit(value);
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2025-2026 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,7 +21,9 @@ import java.io.UncheckedIOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.msgpack.core.MessagePack;
|
||||
import org.msgpack.core.MessageUnpacker;
|
||||
import org.pkl.core.runtime.BaseModule;
|
||||
@@ -111,7 +113,7 @@ public class PklBinaryDecoder extends AbstractPklBinaryDecoder {
|
||||
|
||||
@Override
|
||||
protected Object doDecodeMap(MapDecodeIterator iter) {
|
||||
var map = CollectionUtils.newLinkedHashMap(iter.getSize());
|
||||
Map<@Nullable Object, @Nullable Object> map = CollectionUtils.newLinkedHashMap(iter.getSize());
|
||||
while (iter.hasNext()) {
|
||||
var entry = iter.next();
|
||||
map.put(entry.getFirst(), entry.getSecond());
|
||||
|
||||
@@ -54,6 +54,9 @@ final class PropertiesRenderer implements ValueRenderer {
|
||||
} else if (value instanceof Map<?, ?> map) {
|
||||
doVisitMap(null, map);
|
||||
} else if (value instanceof Pair<?, ?> pair) {
|
||||
// Pair coming from the runtime can never admit null (in-language null is represented as
|
||||
// PNull)
|
||||
//noinspection DataFlowIssue
|
||||
doVisitKeyAndValue(null, pair.getFirst(), pair.getSecond());
|
||||
} else {
|
||||
throw new RendererException(
|
||||
@@ -177,6 +180,13 @@ final class PropertiesRenderer implements ValueRenderer {
|
||||
"Values of type `Regex` cannot be rendered as Properties. Value: %s", value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertReference(Reference value) {
|
||||
throw new RendererException(
|
||||
String.format(
|
||||
"Values of type `Reference` cannot be rendered as Properties. Value: %s", value));
|
||||
}
|
||||
|
||||
private void doVisitMap(@Nullable String keyPrefix, Map<?, ?> map) {
|
||||
for (Map.Entry<?, ?> entry : map.entrySet()) {
|
||||
doVisitKeyAndValue(keyPrefix, entry.getKey(), entry.getValue());
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright © 2026 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.
|
||||
*/
|
||||
package org.pkl.core;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.List;
|
||||
|
||||
public class Reference implements Value {
|
||||
@Serial private static final long serialVersionUID = 0L;
|
||||
|
||||
private final Composite domain;
|
||||
private final Object data;
|
||||
private final List<Composite> path;
|
||||
private final PType referentType;
|
||||
|
||||
/** Constructs a reference. */
|
||||
public Reference(Composite domain, Object data, List<Composite> path, PType referentType) {
|
||||
this.domain = domain;
|
||||
this.data = data;
|
||||
this.path = path;
|
||||
this.referentType = referentType;
|
||||
}
|
||||
|
||||
/** Returns the domain object of this reference. */
|
||||
public Composite getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
/** Returns the data object of this reference. */
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the access path of this reference.
|
||||
*
|
||||
* <p>All elements are exported {@code pkl.ref#Access} instances.
|
||||
*/
|
||||
public List<Composite> getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/** Returns the referent type of this reference. */
|
||||
public PType getReferentType() {
|
||||
return referentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ValueVisitor visitor) {
|
||||
visitor.visitReference(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ValueConverter<T> converter) {
|
||||
return converter.convertReference(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (!(o instanceof Reference reference)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return domain.equals(reference.domain)
|
||||
&& data.equals(reference.data)
|
||||
&& path.equals(reference.path)
|
||||
&& referentType.equals(reference.referentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PClassInfo<?> getClassInfo() {
|
||||
return PClassInfo.Reference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = domain.hashCode();
|
||||
result = 31 * result + data.hashCode();
|
||||
result = 31 * result + path.hashCode();
|
||||
result = 31 * result + referentType.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString();
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ public final class TypeAlias extends Member implements Value {
|
||||
private final String moduleName;
|
||||
private final String qualifiedName;
|
||||
private final List<TypeParameter> typeParameters;
|
||||
private final PClass moduleClass;
|
||||
|
||||
@LateInit private PType aliasedType;
|
||||
|
||||
@@ -39,11 +40,13 @@ public final class TypeAlias extends Member implements Value {
|
||||
String simpleName,
|
||||
String moduleName,
|
||||
String qualifiedName,
|
||||
List<TypeParameter> typeParameters) {
|
||||
List<TypeParameter> typeParameters,
|
||||
PClass moduleClass) {
|
||||
super(docComment, sourceLocation, modifiers, annotations, simpleName);
|
||||
this.moduleName = moduleName;
|
||||
this.qualifiedName = qualifiedName;
|
||||
this.typeParameters = typeParameters;
|
||||
this.moduleClass = moduleClass;
|
||||
}
|
||||
|
||||
public void initAliasedType(PType type) {
|
||||
@@ -79,6 +82,10 @@ public final class TypeAlias extends Member implements Value {
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
public PClass getModuleClass() {
|
||||
return moduleClass;
|
||||
}
|
||||
|
||||
/** Returns the type that this type alias stands for. */
|
||||
public PType getAliasedType() {
|
||||
//noinspection ConstantValue
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 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.core;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import org.pkl.core.util.LateInit;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/** A type parameter of a generic class, type alias, or method. */
|
||||
public final class TypeParameter implements Serializable {
|
||||
@@ -27,7 +27,7 @@ public final class TypeParameter implements Serializable {
|
||||
private final String name;
|
||||
private final int index;
|
||||
|
||||
@LateInit private volatile Member owner;
|
||||
private volatile @Nullable Member owner;
|
||||
|
||||
public TypeParameter(Variance variance, String name, int index) {
|
||||
this.variance = variance;
|
||||
@@ -48,6 +48,7 @@ public final class TypeParameter implements Serializable {
|
||||
/** Returns the generic class, type alias, or method that this type parameter belongs to. */
|
||||
public Member getOwner() {
|
||||
assert owner != null;
|
||||
//noinspection DataFlowIssue
|
||||
return owner;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 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.
|
||||
@@ -57,6 +57,8 @@ public interface ValueConverter<T> {
|
||||
|
||||
T convertRegex(Pattern value);
|
||||
|
||||
T convertReference(Reference value);
|
||||
|
||||
default T convert(Object value) {
|
||||
if (value instanceof Value v) {
|
||||
return (v.accept(this));
|
||||
|
||||
@@ -93,6 +93,10 @@ public interface ValueVisitor {
|
||||
visitDefault(value);
|
||||
}
|
||||
|
||||
default void visitReference(Reference value) {
|
||||
visitDefault(value);
|
||||
}
|
||||
|
||||
default void visit(Object value) {
|
||||
if (value instanceof Value v) {
|
||||
v.accept(this);
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.pkl.core;
|
||||
import java.util.*;
|
||||
import java.util.regex.*;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
/**
|
||||
* A <a href="https://semver.org/spec/v2.0.0.html">semantic version</a>.
|
||||
@@ -59,7 +58,7 @@ public final class Version implements Comparable<Version> {
|
||||
private final @Nullable String preRelease;
|
||||
private final @Nullable String build;
|
||||
|
||||
@LateInit private volatile Identifier[] __preReleaseIdentifiers;
|
||||
private volatile Identifier @Nullable [] __preReleaseIdentifiers;
|
||||
|
||||
/** Constructs a semantic version. */
|
||||
public Version(
|
||||
@@ -230,6 +229,7 @@ public final class Version implements Comparable<Version> {
|
||||
: new Identifier(-1, str))
|
||||
.toArray(Identifier[]::new);
|
||||
}
|
||||
//noinspection DataFlowIssue
|
||||
return __preReleaseIdentifiers;
|
||||
}
|
||||
|
||||
|
||||
@@ -724,7 +724,7 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
// elem
|
||||
// }
|
||||
// }
|
||||
return p.levelsUp() == 0
|
||||
return p.levelsUp() == 0 && !p.needsFrameSkip()
|
||||
? ReadExactFrameSlotNodeGen.create(sourceSection, p.slot())
|
||||
: ReadFrameSlotNodeGen.create(
|
||||
sourceSection, p.slot(), new GetEnclosingFrameNode(p.levelsUp()));
|
||||
@@ -1476,8 +1476,6 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
var scope = (ModuleScope) symbolTable.getCurrentScope();
|
||||
scope.setModifiers(modifiers);
|
||||
|
||||
checkAbstractMembersAllowed(modifiers, mod.getProperties(), mod.getMethods());
|
||||
|
||||
// visit imports first so that we already have the object member name available
|
||||
var imports = mod.getImports();
|
||||
var importMembers = new ObjectMember[imports.size()];
|
||||
@@ -1722,7 +1720,6 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
List<ClassProperty> properties = bodyNode != null ? bodyNode.getProperties() : List.of();
|
||||
List<ClassMethod> methods = bodyNode != null ? bodyNode.getMethods() : List.of();
|
||||
registerClassScopeNames(scope, properties, methods);
|
||||
checkAbstractMembersAllowed(modifiers, properties, methods);
|
||||
|
||||
var supertypeCtx = clazz.getSuperClass();
|
||||
|
||||
@@ -1813,30 +1810,6 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
};
|
||||
}
|
||||
|
||||
private void checkAbstractMembersAllowed(
|
||||
int enclosingModifiers, List<ClassProperty> properties, List<ClassMethod> methods) {
|
||||
if (VmModifier.isAbstract(enclosingModifiers)) {
|
||||
return;
|
||||
}
|
||||
for (var property : properties) {
|
||||
checkMemberNotAbstract(property.getModifiers());
|
||||
}
|
||||
for (var method : methods) {
|
||||
checkMemberNotAbstract(method.getModifiers());
|
||||
}
|
||||
}
|
||||
|
||||
private void checkMemberNotAbstract(List<Modifier> modifiers) {
|
||||
for (var modifier : modifiers) {
|
||||
if (modifier.getValue() == ModifierValue.ABSTRACT) {
|
||||
throw exceptionBuilder()
|
||||
.evalError("abstractMemberInNonAbstractClass")
|
||||
.withSourceSection(createSourceSection(modifier.span()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private UnresolvedPropertyNode[] doVisitClassProperties(
|
||||
List<ClassProperty> propertyContexts, Set<String> propertyNames) {
|
||||
var propertyNodes = new UnresolvedPropertyNode[propertyContexts.size()];
|
||||
|
||||
@@ -509,6 +509,7 @@ public final class SymbolTable {
|
||||
private @Nullable <R> R resolveLexical(ResolutionFunction<R> fun) {
|
||||
var levelsUp = 0;
|
||||
var shouldSkip = false;
|
||||
var skippedObjectScope = false;
|
||||
for (var scope = this; scope != null; scope = scope.getParent()) {
|
||||
// for headers resolve variables one scope up
|
||||
if (scope instanceof EagerGeneratorScope) {
|
||||
@@ -524,11 +525,24 @@ public final class SymbolTable {
|
||||
if (scope instanceof ObjectScope objectScope && objectScope.hasParams()) {
|
||||
levelsUp++;
|
||||
}
|
||||
// An EagerGeneratorScope (for `when` predicates) skipped an ObjectScope.
|
||||
// The ObjectScope may become a parse-time-invisible amend function at runtime,
|
||||
// so for-gen variables at levelsUp == 0 need ReadFrameSlotNode
|
||||
// (which calls skipInvisibleScopes) rather than ReadExactFrameSlotNode.
|
||||
if (scope instanceof ObjectScope) {
|
||||
skippedObjectScope = true;
|
||||
}
|
||||
shouldSkip = false;
|
||||
continue;
|
||||
}
|
||||
var result = fun.apply(lex, levelsUp);
|
||||
if (result != null) return result;
|
||||
if (result != null) {
|
||||
if (result instanceof ForGeneratorVariableOrLetBinding p && skippedObjectScope) {
|
||||
//noinspection unchecked
|
||||
return (R) new ForGeneratorVariableOrLetBinding(p.slot(), p.levelsUp(), true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (scope instanceof MethodScope
|
||||
|| scope instanceof ForGeneratorScope
|
||||
|| scope instanceof LetExpressionScope) {
|
||||
@@ -798,7 +812,7 @@ public final class SymbolTable {
|
||||
return null;
|
||||
}
|
||||
if (name.equals(binding.name())) {
|
||||
return new ForGeneratorVariableOrLetBinding(binding.slot(), levelsUp);
|
||||
return new ForGeneratorVariableOrLetBinding(binding.slot(), levelsUp, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -910,10 +924,10 @@ public final class SymbolTable {
|
||||
@Override
|
||||
public @Nullable VariableResolution doResolveProperty(String name, int levelsUp) {
|
||||
if (keyBinding != null && keyBinding.name().equals(name)) {
|
||||
return new ForGeneratorVariableOrLetBinding(keyBinding.slot(), levelsUp);
|
||||
return new ForGeneratorVariableOrLetBinding(keyBinding.slot(), levelsUp, false);
|
||||
}
|
||||
if (valueBinding != null && valueBinding.name().equals(name)) {
|
||||
return new ForGeneratorVariableOrLetBinding(valueBinding.slot(), levelsUp);
|
||||
return new ForGeneratorVariableOrLetBinding(valueBinding.slot(), levelsUp, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ public sealed interface VariableResolution {
|
||||
// method, lambda, object body param
|
||||
record Parameter(int slot, int levelsUp) implements VariableResolution {}
|
||||
|
||||
record ForGeneratorVariableOrLetBinding(int slot, int levelsUp) implements VariableResolution {}
|
||||
record ForGeneratorVariableOrLetBinding(int slot, int levelsUp, boolean needsFrameSkip)
|
||||
implements VariableResolution {}
|
||||
|
||||
// Implicit base module lookup
|
||||
record ImplicitBaseProperty() implements VariableResolution {}
|
||||
|
||||
@@ -23,7 +23,11 @@ import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.IndirectCallNode;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.runtime.*;
|
||||
import org.pkl.core.runtime.VmReference.VmReferenceAccessError;
|
||||
import org.pkl.core.runtime.VmReference.VmReferenceAccessErrorType;
|
||||
import org.pkl.core.util.ErrorMessages;
|
||||
|
||||
@NodeInfo(shortName = "[]")
|
||||
public abstract class SubscriptNode extends BinaryExpressionNode {
|
||||
@@ -100,6 +104,34 @@ public abstract class SubscriptNode extends BinaryExpressionNode {
|
||||
return readMember(dynamic, key, callNode);
|
||||
}
|
||||
|
||||
private @Nullable String getReferenceHint(
|
||||
VmReference reference, VmReferenceAccessError err, Object key) {
|
||||
var myType = reference.getReferentType();
|
||||
if (err.getErrorType() != VmReferenceAccessErrorType.CANNOT_FIND_MEMBER) {
|
||||
return null;
|
||||
}
|
||||
return err.getType().equals(myType)
|
||||
? ErrorMessages.create("operatorNotDefined2", getShortName(), myType, VmUtils.getClass(key))
|
||||
: ErrorMessages.create(
|
||||
"operatorNotDefined3", getShortName(), myType, err.getType(), VmUtils.getClass(key));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
protected VmReference eval(VmReference reference, Object key) {
|
||||
try {
|
||||
return reference.withSubscriptAccess(key);
|
||||
} catch (VmReferenceAccessError err) {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
throw exceptionBuilder()
|
||||
.evalError(
|
||||
"operatorNotDefined2", getShortName(), reference.exportType(), VmUtils.getClass(key))
|
||||
.withProgramValue("Left operand", reference)
|
||||
.withProgramValue("Right operand", key)
|
||||
.withHint(getReferenceHint(reference, err, key))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
protected long eval(VmBytes receiver, long index) {
|
||||
if (index < 0 || index >= receiver.getLength()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2025-2026 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,19 +20,19 @@ import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.ExplodeLoop;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.ast.type.TypeNode.UInt8TypeAliasTypeNode;
|
||||
import org.pkl.core.ast.type.VmTypeMismatchException;
|
||||
import org.pkl.core.runtime.VmBytes;
|
||||
import org.pkl.core.runtime.VmUtils;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
@NodeInfo(shortName = "Bytes()")
|
||||
public final class BytesLiteralNode extends ExpressionNode {
|
||||
@Children private final ExpressionNode[] elements;
|
||||
|
||||
@Child @LateInit private TypeNode typeNode;
|
||||
@Child private @Nullable TypeNode typeNode;
|
||||
|
||||
public BytesLiteralNode(SourceSection sourceSection, ExpressionNode[] elements) {
|
||||
super(sourceSection);
|
||||
|
||||
+3
-1
@@ -22,6 +22,7 @@ import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.DirectCallNode;
|
||||
import com.oracle.truffle.api.nodes.ExplodeLoop;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.runtime.Identifier;
|
||||
import org.pkl.core.runtime.VmObjectLike;
|
||||
@@ -34,7 +35,7 @@ public abstract sealed class AbstractInvokeMethodLexicalNode extends ExpressionN
|
||||
protected final int levelsUp;
|
||||
private final boolean needsConst;
|
||||
@Children private ExpressionNode[] argumentNodes;
|
||||
@Child private DirectCallNode callNode;
|
||||
@Child private @Nullable DirectCallNode callNode;
|
||||
@CompilationFinal protected boolean isConstChecked;
|
||||
|
||||
protected AbstractInvokeMethodLexicalNode(
|
||||
@@ -90,6 +91,7 @@ public abstract sealed class AbstractInvokeMethodLexicalNode extends ExpressionN
|
||||
callNode = DirectCallNode.create(getCallTarget(owner));
|
||||
insert(callNode);
|
||||
}
|
||||
assert callNode != null;
|
||||
return callNode;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -19,17 +19,17 @@ import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.type.TypeNode.UnknownTypeNode;
|
||||
import org.pkl.core.runtime.*;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
/** Infers the parent to amend in `function createPerson(): Person = new { ... }`. */
|
||||
public final class InferParentWithinMethodNode extends ExpressionNode {
|
||||
private final VmLanguage language;
|
||||
private final Identifier methodName;
|
||||
@Child private ExpressionNode ownerNode;
|
||||
@CompilationFinal @LateInit private Object inferredParent;
|
||||
@Child private @Nullable ExpressionNode ownerNode;
|
||||
@CompilationFinal private @Nullable Object inferredParent;
|
||||
|
||||
public InferParentWithinMethodNode(
|
||||
SourceSection sourceSection,
|
||||
@@ -52,6 +52,7 @@ public final class InferParentWithinMethodNode extends ExpressionNode {
|
||||
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
|
||||
assert ownerNode != null;
|
||||
var owner = (VmObjectLike) ownerNode.executeGeneric(frame);
|
||||
assert owner.isPrototype();
|
||||
|
||||
|
||||
+4
-3
@@ -19,6 +19,7 @@ import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.member.ObjectMethodNode;
|
||||
import org.pkl.core.ast.type.TypeNode.UnknownTypeNode;
|
||||
@@ -26,14 +27,13 @@ import org.pkl.core.runtime.Identifier;
|
||||
import org.pkl.core.runtime.VmDynamic;
|
||||
import org.pkl.core.runtime.VmLanguage;
|
||||
import org.pkl.core.runtime.VmObjectLike;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
/** Infers the parent to amend in `obj { local function createPerson(): Person = new { ... } }`. */
|
||||
public final class InferParentWithinObjectMethodNode extends ExpressionNode {
|
||||
private final VmLanguage language;
|
||||
private final Identifier localMethodName;
|
||||
@Child private ExpressionNode ownerNode;
|
||||
@CompilationFinal @LateInit private Object inferredParent;
|
||||
@Child private @Nullable ExpressionNode ownerNode;
|
||||
@CompilationFinal private @Nullable Object inferredParent;
|
||||
|
||||
public InferParentWithinObjectMethodNode(
|
||||
SourceSection sourceSection,
|
||||
@@ -58,6 +58,7 @@ public final class InferParentWithinObjectMethodNode extends ExpressionNode {
|
||||
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
|
||||
assert ownerNode != null;
|
||||
var owner = (VmObjectLike) ownerNode.executeGeneric(frame);
|
||||
|
||||
var member = owner.getMember(localMethodName);
|
||||
|
||||
+3
-2
@@ -18,6 +18,7 @@ package org.pkl.core.ast.expression.member;
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.MemberLookupMode;
|
||||
import org.pkl.core.ast.expression.primary.GetEnclosingReceiverNode;
|
||||
@@ -49,8 +50,8 @@ public final class ReadAmbiguousLocalityPropertyNode extends ExpressionNode {
|
||||
private final Identifier name;
|
||||
private final int levelsUp;
|
||||
private final boolean needsConst;
|
||||
private @Child ExpressionNode readLocalPropertyNode;
|
||||
private @Child ExpressionNode readPropertyNode;
|
||||
@Child private @Nullable ExpressionNode readLocalPropertyNode;
|
||||
@Child private @Nullable ExpressionNode readPropertyNode;
|
||||
|
||||
public ReadAmbiguousLocalityPropertyNode(
|
||||
SourceSection sourceSection, Identifier name, int levelsUp, boolean needsConst) {
|
||||
|
||||
+4
-2
@@ -22,6 +22,7 @@ import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.DirectCallNode;
|
||||
import com.oracle.truffle.api.nodes.ExplodeLoop;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.PklBugException;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.member.ObjectMember;
|
||||
@@ -34,8 +35,8 @@ public final class ReadLocalPropertyNode extends ExpressionNode {
|
||||
private final Identifier name;
|
||||
private final int levelsUp;
|
||||
private final boolean needsConst;
|
||||
@Child private DirectCallNode callNode;
|
||||
@CompilationFinal private ObjectMember property;
|
||||
@Child private @Nullable DirectCallNode callNode;
|
||||
@CompilationFinal @Nullable private ObjectMember property;
|
||||
|
||||
public ReadLocalPropertyNode(
|
||||
SourceSection sourceSection, Identifier name, int levelsUp, boolean needsConst) {
|
||||
@@ -91,6 +92,7 @@ public final class ReadLocalPropertyNode extends ExpressionNode {
|
||||
callNode = DirectCallNode.create(property.getCallTarget());
|
||||
insert(callNode);
|
||||
}
|
||||
assert callNode != null;
|
||||
return callNode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,13 @@ import com.oracle.truffle.api.nodes.IndirectCallNode;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.PType;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.MemberLookupMode;
|
||||
import org.pkl.core.ast.member.ClassProperty;
|
||||
import org.pkl.core.runtime.*;
|
||||
import org.pkl.core.runtime.VmReference.VmReferenceAccessError;
|
||||
import org.pkl.core.util.ErrorMessages;
|
||||
|
||||
@NodeInfo(shortName = ".")
|
||||
@ImportStatic(BaseModule.class)
|
||||
@@ -61,6 +64,40 @@ public abstract class ReadPropertyNode extends ExpressionNode {
|
||||
this(sourceSection, propertyName, MemberLookupMode.EXPLICIT_RECEIVER, false);
|
||||
}
|
||||
|
||||
protected String getReferenceErrorHint(VmReference reference, VmReferenceAccessError err) {
|
||||
var myType = reference.getReferentType();
|
||||
return switch (err.getErrorType()) {
|
||||
case CANNOT_FIND_MEMBER ->
|
||||
err.getType().equals(myType)
|
||||
? ErrorMessages.create("cannotFindPropertyInType", propertyName, myType)
|
||||
: ErrorMessages.create(
|
||||
"cannotFindPropertyInType2", propertyName, myType, err.getType());
|
||||
case EXTERNAL_MEMBER ->
|
||||
ErrorMessages.create("cannotReferenceExternalProperty", propertyName, err.getType());
|
||||
case DEFAULT_MEMBER ->
|
||||
ErrorMessages.create(
|
||||
"cannotReferenceDefaultProperty",
|
||||
((PType.Class) err.getType()).getPClass().getSimpleName());
|
||||
case EXTERNAL_CLASS ->
|
||||
ErrorMessages.create(
|
||||
"cannotReferencePropertyInExternalClass", propertyName, err.getType());
|
||||
};
|
||||
}
|
||||
|
||||
@Specialization
|
||||
protected VmReference evalReference(VmReference receiver) {
|
||||
assert lookupMode == MemberLookupMode.EXPLICIT_RECEIVER;
|
||||
try {
|
||||
return receiver.withPropertyAccess(propertyName);
|
||||
} catch (VmReferenceAccessError err) {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
throw exceptionBuilder()
|
||||
.evalError("cannotFindPropertyInObjectNoHint", propertyName, receiver.exportType())
|
||||
.withHint(getReferenceErrorHint(receiver, err))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
// This method effectively covers `VmObject receiver` but is implemented in a more
|
||||
// efficient way. See:
|
||||
// https://www.graalvm.org/22.0/graalvm-as-a-platform/language-implementation-framework/TruffleLibraries/#strategy-2-java-interfaces
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.SecurityManagerException;
|
||||
import org.pkl.core.ast.member.SharedMemberNode;
|
||||
import org.pkl.core.externalreader.ExternalReaderProcessException;
|
||||
@@ -35,13 +36,12 @@ import org.pkl.core.runtime.VmMapping;
|
||||
import org.pkl.core.runtime.VmObjectBuilder;
|
||||
import org.pkl.core.util.GlobResolver;
|
||||
import org.pkl.core.util.GlobResolver.InvalidGlobPatternException;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
@NodeInfo(shortName = "import*")
|
||||
public class ImportGlobNode extends AbstractImportNode {
|
||||
private final String globPattern;
|
||||
@Child @LateInit private SharedMemberNode memberNode;
|
||||
@CompilationFinal @LateInit private VmMapping cachedResult;
|
||||
@Child private @Nullable SharedMemberNode memberNode;
|
||||
@CompilationFinal private @Nullable VmMapping cachedResult;
|
||||
|
||||
public ImportGlobNode(
|
||||
SourceSection sourceSection,
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import java.net.URI;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.SecurityManagerException;
|
||||
import org.pkl.core.http.HttpClientException;
|
||||
import org.pkl.core.module.ResolvedModuleKey;
|
||||
@@ -28,13 +29,12 @@ import org.pkl.core.packages.PackageLoadError;
|
||||
import org.pkl.core.runtime.VmContext;
|
||||
import org.pkl.core.runtime.VmLanguage;
|
||||
import org.pkl.core.runtime.VmTyped;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
@NodeInfo(shortName = "import")
|
||||
public final class ImportNode extends AbstractImportNode {
|
||||
private final VmLanguage language;
|
||||
|
||||
@CompilationFinal @LateInit private VmTyped importedModule;
|
||||
@CompilationFinal private @Nullable VmTyped importedModule;
|
||||
|
||||
public ImportNode(
|
||||
VmLanguage language,
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.oracle.truffle.api.source.SourceSection;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import org.graalvm.collections.EconomicMap;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.SecurityManagerException;
|
||||
import org.pkl.core.ast.member.SharedMemberNode;
|
||||
import org.pkl.core.externalreader.ExternalReaderProcessException;
|
||||
@@ -36,12 +37,11 @@ import org.pkl.core.runtime.VmObjectBuilder;
|
||||
import org.pkl.core.util.GlobResolver;
|
||||
import org.pkl.core.util.GlobResolver.InvalidGlobPatternException;
|
||||
import org.pkl.core.util.IoUtils;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
@NodeInfo(shortName = "read*")
|
||||
public abstract class ReadGlobNode extends AbstractReadNode {
|
||||
private final EconomicMap<String, VmMapping> cachedResults = EconomicMap.create();
|
||||
@Child @LateInit private SharedMemberNode memberNode;
|
||||
@Child private @Nullable SharedMemberNode memberNode;
|
||||
|
||||
protected ReadGlobNode(SourceSection sourceSection, ModuleKey currentModule) {
|
||||
super(sourceSection, currentModule);
|
||||
@@ -67,6 +67,7 @@ public abstract class ReadGlobNode extends AbstractReadNode {
|
||||
@TruffleBoundary
|
||||
public Object read(String globPattern) {
|
||||
var cachedResult = cachedResults.get(globPattern);
|
||||
//noinspection ConstantValue
|
||||
if (cachedResult != null) return cachedResult;
|
||||
|
||||
// use same check as for globbed imports (see AstBuilder)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 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,6 +20,7 @@ import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.DirectCallNode;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.MemberLookupMode;
|
||||
@@ -62,10 +63,18 @@ public abstract class ToStringNode extends UnaryExpressionNode {
|
||||
VmTyped value,
|
||||
@Cached(value = "createInvokeNode()", neverDefault = true)
|
||||
InvokeMethodVirtualNode invokeNode) {
|
||||
|
||||
return (String) invokeNode.executeWith(frame, value, value.getVmClass());
|
||||
}
|
||||
|
||||
@Specialization
|
||||
protected String evalReference(
|
||||
VirtualFrame frame,
|
||||
VmReference value,
|
||||
@Cached(value = "createReferenceCallNode(value)", neverDefault = true)
|
||||
DirectCallNode callNode) {
|
||||
return (String) callNode.call(value, value.getVmClass().getPrototype());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
@Override
|
||||
@TruffleBoundary
|
||||
@@ -74,7 +83,6 @@ public abstract class ToStringNode extends UnaryExpressionNode {
|
||||
}
|
||||
|
||||
protected InvokeMethodVirtualNode createInvokeNode() {
|
||||
//noinspection ConstantConditions
|
||||
return InvokeMethodVirtualNodeGen.create(
|
||||
sourceSection,
|
||||
Identifier.TO_STRING,
|
||||
@@ -83,4 +91,10 @@ public abstract class ToStringNode extends UnaryExpressionNode {
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
protected DirectCallNode createReferenceCallNode(VmReference reference) {
|
||||
var toStringMethod = reference.getVmClass().getDeclaredMethod(Identifier.TO_STRING);
|
||||
assert toStringMethod != null;
|
||||
return DirectCallNode.create(toStringMethod.getCallTarget());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.pkl.core.TypeParameter;
|
||||
import org.pkl.core.ast.VmModifier;
|
||||
import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.runtime.*;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
public final class ClassMethod extends ClassMember {
|
||||
private final List<TypeParameter> typeParameters;
|
||||
@@ -33,7 +34,7 @@ public final class ClassMethod extends ClassMember {
|
||||
// null = not deprecated, "" = no/empty message in the @Deprecated body
|
||||
private final @Nullable String deprecation;
|
||||
|
||||
@CompilationFinal private FunctionNode functionNode;
|
||||
@CompilationFinal @LateInit private FunctionNode functionNode;
|
||||
|
||||
public ClassMethod(
|
||||
SourceSection sourceSection,
|
||||
@@ -61,6 +62,7 @@ public final class ClassMethod extends ClassMember {
|
||||
}
|
||||
|
||||
public void initFunctionNode(FunctionNode functionNode) {
|
||||
//noinspection ConstantValue
|
||||
assert this.functionNode == null;
|
||||
this.functionNode = functionNode;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ public final class ClassNode extends ExpressionNode {
|
||||
// Caching of classes also guarantees that classes are singletons and can be compared by
|
||||
// identity,
|
||||
// which improves efficiency and performance (for example in shape checks).
|
||||
//noinspection ConstantValue
|
||||
if (cachedClass != null) return cachedClass;
|
||||
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.pkl.core.ast.member;
|
||||
import com.oracle.truffle.api.frame.FrameDescriptor;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.PklRootNode;
|
||||
import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.runtime.VmLanguage;
|
||||
@@ -46,7 +45,7 @@ public final class ListingOrMappingTypeCastNode extends PklRootNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getName() {
|
||||
public String getName() {
|
||||
return qualifiedName;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,12 +23,11 @@ import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.ast.type.UnresolvedTypeNode;
|
||||
import org.pkl.core.runtime.VmLanguage;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
public final class LocalTypedPropertyNode extends RegularMemberNode {
|
||||
private final VmLanguage language;
|
||||
@Child private UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child @LateInit private TypeNode typeNode;
|
||||
@Child private @Nullable UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child private @Nullable TypeNode typeNode;
|
||||
private @Nullable Object defaultValue;
|
||||
private boolean defaultValueInitialized;
|
||||
|
||||
@@ -47,6 +46,7 @@ public final class LocalTypedPropertyNode extends RegularMemberNode {
|
||||
|
||||
public @Nullable Object getDefaultValue(VirtualFrame frame) {
|
||||
if (!defaultValueInitialized) {
|
||||
assert typeNode != null;
|
||||
defaultValue =
|
||||
typeNode.createDefaultValue(
|
||||
frame, language, member.getHeaderSection(), member.getQualifiedName());
|
||||
@@ -59,6 +59,7 @@ public final class LocalTypedPropertyNode extends RegularMemberNode {
|
||||
protected Object executeImpl(VirtualFrame frame) {
|
||||
if (typeNode == null) {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
assert unresolvedTypeNode != null;
|
||||
typeNode = insert(unresolvedTypeNode.execute(frame));
|
||||
unresolvedTypeNode = null;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.ast.type.UnresolvedTypeNode;
|
||||
import org.pkl.core.runtime.*;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
public final class ObjectMethodNode extends RegularMemberNode {
|
||||
private final VmLanguage language;
|
||||
@@ -33,7 +32,7 @@ public final class ObjectMethodNode extends RegularMemberNode {
|
||||
@Children private final @Nullable UnresolvedTypeNode[] unresolvedParameterTypeNodes;
|
||||
@Child private @Nullable UnresolvedTypeNode unresolvedReturnTypeNode;
|
||||
|
||||
@CompilationFinal @LateInit private FunctionNode functionNode;
|
||||
@CompilationFinal private @Nullable FunctionNode functionNode;
|
||||
|
||||
public ObjectMethodNode(
|
||||
VmLanguage language,
|
||||
|
||||
@@ -31,7 +31,7 @@ public final class UnresolvedFunctionNode extends PklNode {
|
||||
private final int parameterCount;
|
||||
@Children private final @Nullable UnresolvedTypeNode[] unresolvedParameterTypeNodes;
|
||||
@Child private @Nullable UnresolvedTypeNode unresolvedReturnTypeNode;
|
||||
private final ExpressionNode bodyNode;
|
||||
@Child private ExpressionNode bodyNode;
|
||||
|
||||
public UnresolvedFunctionNode(
|
||||
VmLanguage language,
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.runtime.*;
|
||||
import org.pkl.core.util.LateInit;
|
||||
@@ -26,7 +27,7 @@ import org.pkl.core.util.LateInit;
|
||||
/** Resolves `<type>` to the type's default value in `new <type> { ... }`. */
|
||||
public final class GetParentForTypeNode extends ExpressionNode {
|
||||
@Child private UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child private TypeNode typeNode;
|
||||
@Child private @Nullable TypeNode typeNode;
|
||||
private final String qualifiedName;
|
||||
|
||||
@CompilationFinal @LateInit Object defaultValue;
|
||||
@@ -49,6 +50,7 @@ public final class GetParentForTypeNode extends ExpressionNode {
|
||||
|
||||
@Override
|
||||
public Object executeGeneric(VirtualFrame frame) {
|
||||
//noinspection ConstantValue
|
||||
if (defaultValue != null) return defaultValue;
|
||||
CompilerDirectives.transferToInterpreterAndInvalidate();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 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,14 +19,14 @@ import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
@NodeInfo(shortName = "as")
|
||||
public final class TypeCastNode extends ExpressionNode {
|
||||
@Child private ExpressionNode valueNode;
|
||||
@Child private UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child @LateInit private TypeNode typeNode;
|
||||
@Child private @Nullable UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child private @Nullable TypeNode typeNode;
|
||||
|
||||
public TypeCastNode(
|
||||
SourceSection sourceSection,
|
||||
@@ -43,6 +43,7 @@ public final class TypeCastNode extends ExpressionNode {
|
||||
// don't compile unresolvedTypeNode.execute()
|
||||
// invalidation is done by insert()
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
assert unresolvedTypeNode != null;
|
||||
typeNode = insert(unresolvedTypeNode.execute(frame));
|
||||
unresolvedTypeNode = null;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,10 @@ import com.oracle.truffle.api.frame.FrameSlotKind;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.ExplodeLoop;
|
||||
import com.oracle.truffle.api.nodes.LoopNode;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.nodes.NodeUtil;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -38,6 +41,7 @@ import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.PType;
|
||||
import org.pkl.core.PType.StringLiteral;
|
||||
import org.pkl.core.PklBugException;
|
||||
import org.pkl.core.StackFrame;
|
||||
import org.pkl.core.TypeParameter;
|
||||
import org.pkl.core.ast.*;
|
||||
import org.pkl.core.ast.builder.SymbolTable.CustomThisScope;
|
||||
@@ -54,6 +58,7 @@ import org.pkl.core.util.EconomicMaps;
|
||||
import org.pkl.core.util.EconomicSets;
|
||||
import org.pkl.core.util.LateInit;
|
||||
import org.pkl.core.util.MutableBoolean;
|
||||
import org.pkl.core.util.MutableReference;
|
||||
|
||||
public abstract class TypeNode extends PklNode {
|
||||
|
||||
@@ -234,7 +239,7 @@ public abstract class TypeNode extends PklNode {
|
||||
public abstract static class FrameSlotTypeNode extends TypeNode {
|
||||
@CompilationFinal protected int slot = -1;
|
||||
|
||||
@CompilationFinal @Child protected WriteFrameSlotNode writeFrameSlotNode;
|
||||
@CompilationFinal @Child protected @Nullable WriteFrameSlotNode writeFrameSlotNode;
|
||||
|
||||
protected FrameSlotTypeNode(SourceSection sourceSection) {
|
||||
super(sourceSection);
|
||||
@@ -844,19 +849,14 @@ public abstract class TypeNode extends PklNode {
|
||||
|
||||
public static class UnionTypeNode extends WriteFrameSlotTypeNode {
|
||||
@Children final TypeNode[] elementTypeNodes;
|
||||
private final boolean skipElementTypeChecks;
|
||||
private final int defaultIndex;
|
||||
|
||||
public UnionTypeNode(
|
||||
SourceSection sourceSection,
|
||||
int defaultIndex,
|
||||
TypeNode[] elementTypeNodes,
|
||||
boolean skipElementTypeChecks) {
|
||||
SourceSection sourceSection, int defaultIndex, TypeNode[] elementTypeNodes) {
|
||||
super(sourceSection);
|
||||
assert elementTypeNodes.length > 0;
|
||||
this.elementTypeNodes = elementTypeNodes;
|
||||
this.defaultIndex = defaultIndex;
|
||||
this.skipElementTypeChecks = skipElementTypeChecks;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -874,7 +874,10 @@ public abstract class TypeNode extends PklNode {
|
||||
|
||||
@Override
|
||||
public boolean isNoopTypeCheck() {
|
||||
return skipElementTypeChecks;
|
||||
for (var element : elementTypeNodes) {
|
||||
if (!element.isNoopTypeCheck()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -980,8 +983,6 @@ public abstract class TypeNode extends PklNode {
|
||||
@Fallback
|
||||
@ExplodeLoop
|
||||
protected Object executeLazily(VirtualFrame frame, Object value) {
|
||||
if (skipElementTypeChecks) return value;
|
||||
|
||||
// escape analysis should remove this allocation in compiled code
|
||||
var typeMismatches = new VmTypeMismatchException[elementTypeNodes.length];
|
||||
|
||||
@@ -1032,8 +1033,6 @@ public abstract class TypeNode extends PklNode {
|
||||
|
||||
@Override
|
||||
public Object executeEagerly(VirtualFrame frame, Object value) {
|
||||
if (skipElementTypeChecks) return value;
|
||||
|
||||
// escape analysis should remove this allocation in compiled code
|
||||
var typeMismatches = new VmTypeMismatchException[elementTypeNodes.length];
|
||||
|
||||
@@ -1157,7 +1156,6 @@ public abstract class TypeNode extends PklNode {
|
||||
@Child private TypeNode elementTypeNode;
|
||||
|
||||
public CollectionTypeNode(SourceSection sourceSection, TypeNode elementTypeNode) {
|
||||
|
||||
super(sourceSection);
|
||||
this.elementTypeNode = elementTypeNode;
|
||||
}
|
||||
@@ -1267,12 +1265,10 @@ public abstract class TypeNode extends PklNode {
|
||||
|
||||
public static final class ListTypeNode extends ObjectSlotTypeNode {
|
||||
@Child private TypeNode elementTypeNode;
|
||||
private final boolean skipElementTypeChecks;
|
||||
|
||||
public ListTypeNode(SourceSection sourceSection, TypeNode elementTypeNode) {
|
||||
super(sourceSection);
|
||||
this.elementTypeNode = elementTypeNode;
|
||||
skipElementTypeChecks = elementTypeNode.isNoopTypeCheck();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1317,7 +1313,7 @@ public abstract class TypeNode extends PklNode {
|
||||
if (!(value instanceof VmList vmList)) {
|
||||
throw typeMismatch(value, BaseModule.getListClass());
|
||||
}
|
||||
if (skipElementTypeChecks) return vmList;
|
||||
if (elementTypeNode.isNoopTypeCheck()) return vmList;
|
||||
|
||||
for (var elem : vmList) {
|
||||
elementTypeNode.executeEagerly(frame, elem);
|
||||
@@ -1334,7 +1330,7 @@ public abstract class TypeNode extends PklNode {
|
||||
if (!(value instanceof VmList vmList)) {
|
||||
throw typeMismatch(value, BaseModule.getListClass());
|
||||
}
|
||||
if (skipElementTypeChecks) return vmList;
|
||||
if (elementTypeNode.isNoopTypeCheck()) return vmList;
|
||||
var ret = vmList;
|
||||
var idx = 0;
|
||||
|
||||
@@ -1366,12 +1362,10 @@ public abstract class TypeNode extends PklNode {
|
||||
|
||||
public abstract static class SetTypeNode extends ObjectSlotTypeNode {
|
||||
@Child private TypeNode elementTypeNode;
|
||||
private final boolean skipElementTypeChecks;
|
||||
|
||||
protected SetTypeNode(SourceSection sourceSection, TypeNode elementTypeNode) {
|
||||
super(sourceSection);
|
||||
this.elementTypeNode = elementTypeNode;
|
||||
skipElementTypeChecks = elementTypeNode.isNoopTypeCheck();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1421,7 +1415,7 @@ public abstract class TypeNode extends PklNode {
|
||||
|
||||
@Specialization
|
||||
protected Object eval(VirtualFrame frame, VmSet value) {
|
||||
if (skipElementTypeChecks) return value;
|
||||
if (elementTypeNode.isNoopTypeCheck()) return value;
|
||||
for (var elem : value) {
|
||||
// no point doing a lazy check because set members have their hash code computed, which
|
||||
// necessarily deep-forces them.
|
||||
@@ -1446,14 +1440,11 @@ public abstract class TypeNode extends PklNode {
|
||||
public static final class MapTypeNode extends ObjectSlotTypeNode {
|
||||
@Child private TypeNode keyTypeNode;
|
||||
@Child private TypeNode valueTypeNode;
|
||||
private final boolean skipEntryTypeChecks;
|
||||
|
||||
public MapTypeNode(SourceSection sourceSection, TypeNode keyTypeNode, TypeNode valueTypeNode) {
|
||||
|
||||
super(sourceSection);
|
||||
this.keyTypeNode = keyTypeNode;
|
||||
this.valueTypeNode = valueTypeNode;
|
||||
skipEntryTypeChecks = keyTypeNode.isNoopTypeCheck() && valueTypeNode.isNoopTypeCheck();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1526,7 +1517,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
private Object eval(VirtualFrame frame, VmMap value) {
|
||||
if (skipEntryTypeChecks) return value;
|
||||
if (keyTypeNode.isNoopTypeCheck() && valueTypeNode.isNoopTypeCheck()) return value;
|
||||
var ret = value;
|
||||
|
||||
for (var entry : value) {
|
||||
@@ -1543,7 +1534,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
private Object evalEager(VirtualFrame frame, VmMap value) {
|
||||
if (skipEntryTypeChecks) return value;
|
||||
if (keyTypeNode.isNoopTypeCheck() && valueTypeNode.isNoopTypeCheck()) return value;
|
||||
for (var entry : value) {
|
||||
keyTypeNode.executeEagerly(frame, VmUtils.getKey(entry));
|
||||
valueTypeNode.executeEagerly(frame, VmUtils.getValue(entry));
|
||||
@@ -1707,9 +1698,6 @@ public abstract class TypeNode extends PklNode {
|
||||
@Child protected TypeNode valueTypeNode;
|
||||
@Child @Nullable protected ListingOrMappingTypeCastNode valueTypeCastNode;
|
||||
|
||||
private final boolean skipKeyTypeChecks;
|
||||
private final boolean skipValueTypeChecks;
|
||||
|
||||
protected ListingOrMappingTypeNode(
|
||||
SourceSection sourceSection,
|
||||
VmLanguage language,
|
||||
@@ -1720,9 +1708,6 @@ public abstract class TypeNode extends PklNode {
|
||||
this.language = language;
|
||||
this.keyTypeNode = keyTypeNode;
|
||||
this.valueTypeNode = valueTypeNode;
|
||||
|
||||
skipKeyTypeChecks = keyTypeNode == null || keyTypeNode.isNoopTypeCheck();
|
||||
skipValueTypeChecks = valueTypeNode.isNoopTypeCheck();
|
||||
}
|
||||
|
||||
private boolean isListing() {
|
||||
@@ -1844,7 +1829,11 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
protected void doEagerCheck(VirtualFrame frame, VmObject object) {
|
||||
doEagerCheck(frame, object, skipKeyTypeChecks, skipValueTypeChecks);
|
||||
doEagerCheck(
|
||||
frame,
|
||||
object,
|
||||
keyTypeNode == null || keyTypeNode.isNoopTypeCheck(),
|
||||
valueTypeNode.isNoopTypeCheck());
|
||||
}
|
||||
|
||||
protected void doEagerCheck(
|
||||
@@ -2127,13 +2116,136 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class ReferenceTypeNode extends ValidatingObjectSlotTypeNode {
|
||||
@Child private TypeNode domainTypeNode;
|
||||
@Child private TypeNode referentTypeNode;
|
||||
@Child private ExpressionNode getModuleNode;
|
||||
|
||||
public ReferenceTypeNode(
|
||||
SourceSection sourceSection, TypeNode domainTypeNode, TypeNode referentTypeNode) {
|
||||
super(sourceSection);
|
||||
this.domainTypeNode = domainTypeNode;
|
||||
this.referentTypeNode = referentTypeNode;
|
||||
this.getModuleNode = new GetModuleNode(sourceSection);
|
||||
validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getValidationErrorKey() {
|
||||
return "invalidReferenceTypeAnnotationWithConstraint";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final @Nullable Node getViolatingNode() {
|
||||
// constraints may not be used in Reference type annotation referents
|
||||
// walk the type and throw if any part of the referent is constrained
|
||||
var violation = new MutableReference<Node>(null);
|
||||
referentTypeNode.acceptTypeNode(
|
||||
true,
|
||||
(typeNode) -> {
|
||||
if (typeNode instanceof ConstrainedTypeNode) {
|
||||
violation.set(typeNode);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return violation.getOrNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean isIncludedInTrace(Node node) {
|
||||
return node instanceof ReferenceTypeNode || node instanceof ConstrainedTypeNode;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
protected Object eval(VirtualFrame frame, VmReference value) {
|
||||
if (domainTypeNode.isNoopTypeCheck() && referentTypeNode.isNoopTypeCheck()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
try {
|
||||
domainTypeNode.execute(frame, value.getDomain());
|
||||
} catch (VmTypeMismatchException e) {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
throw new VmTypeMismatchException.Reference(
|
||||
sourceSection,
|
||||
value,
|
||||
TypeNode.export(domainTypeNode),
|
||||
TypeNode.export(referentTypeNode));
|
||||
}
|
||||
|
||||
var module = (VmTyped) getModuleNode.executeGeneric(frame);
|
||||
return doEval(value, module);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
private Object doEval(VmReference value, VmTyped module) {
|
||||
var referentType = TypeNode.export(referentTypeNode);
|
||||
if (value.referentTypeIsSubtypeOf(referentType, module.getVmClass().export())) {
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new VmTypeMismatchException.Reference(
|
||||
sourceSection, value, TypeNode.export(domainTypeNode), referentType);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
protected Object fallback(Object value) {
|
||||
throw typeMismatch(value, RefModule.getReferenceClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acceptTypeNode(boolean visitTypeArguments, TypeNodeConsumer consumer) {
|
||||
if (visitTypeArguments)
|
||||
return consumer.accept(this)
|
||||
&& consumer.accept(domainTypeNode)
|
||||
&& consumer.accept(referentTypeNode);
|
||||
return consumer.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmClass getVmClass() {
|
||||
return RefModule.getReferenceClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmList getTypeArgumentMirrors() {
|
||||
return VmList.of(domainTypeNode.getMirror(), referentTypeNode.getMirror());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof ReferenceTypeNode referenceTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
return referentTypeNode.isEquivalentTo(referenceTypeNode.referentTypeNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNoopTypeCheck() {
|
||||
return domainTypeNode.isNoopTypeCheck() && referentTypeNode.isNoopTypeCheck();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PType doExport() {
|
||||
return new PType.Class(
|
||||
RefModule.getReferenceClass().export(),
|
||||
domainTypeNode.doExport(),
|
||||
referentTypeNode.doExport());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isParametric() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PairTypeNode extends ObjectSlotTypeNode {
|
||||
@Child private TypeNode firstTypeNode;
|
||||
@Child private TypeNode secondTypeNode;
|
||||
|
||||
public PairTypeNode(
|
||||
SourceSection sourceSection, TypeNode firstTypeNode, TypeNode secondTypeNode) {
|
||||
|
||||
super(sourceSection);
|
||||
this.firstTypeNode = firstTypeNode;
|
||||
this.secondTypeNode = secondTypeNode;
|
||||
@@ -2585,12 +2697,23 @@ public abstract class TypeNode extends PklNode {
|
||||
this.typeAlias = typeAlias;
|
||||
this.typeArgumentNodes = typeArgumentNodes;
|
||||
aliasedTypeNode = typeAlias.instantiate(typeArgumentNodes);
|
||||
aliasedTypeNode.accept(
|
||||
node -> {
|
||||
if (node instanceof ValidatingObjectSlotTypeNode typeNode) {
|
||||
typeNode.validate(this);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public TypeNode getAliasedTypeNode() {
|
||||
return aliasedTypeNode;
|
||||
}
|
||||
|
||||
public VmTypeAlias getTypeAlias() {
|
||||
return typeAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrameSlotKind getFrameSlotKind() {
|
||||
return aliasedTypeNode.getFrameSlotKind();
|
||||
@@ -2633,6 +2756,21 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object executeEagerly(VirtualFrame frame, Object value) {
|
||||
var prevOwner = VmUtils.getOwner(frame);
|
||||
var prevReceiver = VmUtils.getReceiver(frame);
|
||||
setOwner(frame, VmUtils.getOwner(typeAlias.getEnclosingFrame()));
|
||||
setReceiver(frame, VmUtils.getReceiver(typeAlias.getEnclosingFrame()));
|
||||
|
||||
try {
|
||||
return aliasedTypeNode.executeEagerly(frame, value);
|
||||
} finally {
|
||||
setOwner(frame, prevOwner);
|
||||
setReceiver(frame, prevReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
/** See docstring on {@link TypeAliasTypeNode#executeLazily}. */
|
||||
@Override
|
||||
public Object executeAndSet(VirtualFrame frame, Object value) {
|
||||
@@ -3081,6 +3219,78 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class ValidatingObjectSlotTypeNode extends ObjectSlotTypeNode {
|
||||
|
||||
protected ValidatingObjectSlotTypeNode(SourceSection sourceSection) {
|
||||
super(sourceSection);
|
||||
}
|
||||
|
||||
protected abstract String getValidationErrorKey();
|
||||
|
||||
protected abstract @Nullable Node getViolatingNode();
|
||||
|
||||
protected final void validate() {
|
||||
var violation = getViolatingNode();
|
||||
if (violation == null) return;
|
||||
throw exceptionBuilder()
|
||||
.evalError(getValidationErrorKey())
|
||||
.withLeadingStackFrames(buildLeadingFrames(violation, getSourceSection(), null))
|
||||
.build();
|
||||
}
|
||||
|
||||
public final void validate(TypeAliasTypeNode outermostAliasNode) {
|
||||
var violation = getViolatingNode();
|
||||
if (violation == null) return;
|
||||
|
||||
throw exceptionBuilder()
|
||||
.withLocation(outermostAliasNode)
|
||||
.evalError(getValidationErrorKey())
|
||||
.withLeadingStackFrames(
|
||||
buildLeadingFrames(
|
||||
violation,
|
||||
outermostAliasNode.getSourceSection(),
|
||||
outermostAliasNode.getTypeAlias()))
|
||||
.build();
|
||||
}
|
||||
|
||||
protected abstract boolean isIncludedInTrace(Node node);
|
||||
|
||||
private List<StackFrame> buildLeadingFrames(
|
||||
Node violatingNode, SourceSection usageSection, @Nullable VmTypeAlias outermostAlias) {
|
||||
var frames = new ArrayList<StackFrame>();
|
||||
for (var node = violatingNode; node != null; node = node.getParent()) {
|
||||
if (!(node instanceof TypeAliasTypeNode || isIncludedInTrace(node))) continue;
|
||||
var section = node.getSourceSection();
|
||||
if (section == null || !section.isAvailable() || isWithin(usageSection, section)) {
|
||||
continue;
|
||||
}
|
||||
var owner = ownerAlias(node, outermostAlias);
|
||||
if (owner != null) {
|
||||
frames.add(VmUtils.createStackFrame(section, owner.getQualifiedName()));
|
||||
}
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type alias whose body contains {@code node}: the nearest enclosing alias, else the
|
||||
* outermost alias being instantiated (which is {@code null} when no alias is used).
|
||||
*/
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
private static @Nullable VmTypeAlias ownerAlias(
|
||||
Node node, @Nullable VmTypeAlias outermostAlias) {
|
||||
var parent = NodeUtil.findParent(node, TypeAliasTypeNode.class);
|
||||
//noinspection ConstantValue
|
||||
return parent != null ? parent.getTypeAlias() : outermostAlias;
|
||||
}
|
||||
|
||||
private static boolean isWithin(SourceSection outer, SourceSection inner) {
|
||||
return inner.getSource().equals(outer.getSource())
|
||||
&& inner.getCharIndex() >= outer.getCharIndex()
|
||||
&& inner.getCharEndIndex() <= outer.getCharEndIndex();
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable Object createDefaultValue(VmClass clazz) {
|
||||
if (clazz.isInstantiable()) {
|
||||
if (clazz.isListingClass()) return VmListing.empty();
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.pkl.core.runtime.VmLanguage;
|
||||
@NodeInfo(shortName = "is")
|
||||
public final class TypeTestNode extends ExpressionNode {
|
||||
@Child private ExpressionNode valueNode;
|
||||
@Child private UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child private @Nullable UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child private @Nullable TypeNode typeNode;
|
||||
|
||||
public TypeTestNode(
|
||||
@@ -49,6 +49,7 @@ public final class TypeTestNode extends ExpressionNode {
|
||||
// don't compile unresolvedTypeNode.execute()
|
||||
// invalidation is done by insert()
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
assert unresolvedTypeNode != null;
|
||||
typeNode = insert(unresolvedTypeNode.execute(frame));
|
||||
unresolvedTypeNode = null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 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,7 +39,7 @@ public abstract class UnresolvedTypeNode extends PklNode {
|
||||
|
||||
private final VmLanguage language;
|
||||
@Child UnresolvedTypeNode childNode;
|
||||
TypeConstraintNode[] constraintCheckNodes;
|
||||
@Children TypeConstraintNode[] constraintCheckNodes;
|
||||
|
||||
public Constrained(
|
||||
SourceSection sourceSection,
|
||||
@@ -287,6 +287,13 @@ public abstract class UnresolvedTypeNode extends PklNode {
|
||||
return new VarArgsTypeNode(sourceSection, typeArgumentNodes[0].execute(frame));
|
||||
}
|
||||
|
||||
if (clazz.isReferenceClass()) {
|
||||
return ReferenceTypeNodeGen.create(
|
||||
sourceSection,
|
||||
typeArgumentNodes[0].execute(frame),
|
||||
typeArgumentNodes[1].execute(frame));
|
||||
}
|
||||
|
||||
throw exceptionBuilder()
|
||||
.evalError("notAParameterizableClass", clazz.getDisplayName())
|
||||
.withSourceSection(typeArgumentNodes[0].sourceSection)
|
||||
@@ -354,16 +361,13 @@ public abstract class UnresolvedTypeNode extends PklNode {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
|
||||
var elementTypeNodes = new TypeNode[unresolvedElementTypeNodes.length];
|
||||
var skipElementTypeChecks = true;
|
||||
|
||||
for (var i = 0; i < elementTypeNodes.length; i++) {
|
||||
var elementTypeNode = unresolvedElementTypeNodes[i].execute(frame);
|
||||
elementTypeNodes[i] = elementTypeNode;
|
||||
skipElementTypeChecks &= elementTypeNode.isNoopTypeCheck();
|
||||
}
|
||||
|
||||
return new UnionTypeNode(
|
||||
sourceSection, defaultIndex, elementTypeNodes, skipElementTypeChecks);
|
||||
return new UnionTypeNode(sourceSection, defaultIndex, elementTypeNodes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,6 +426,10 @@ public abstract class UnresolvedTypeNode extends PklNode {
|
||||
this.typeParameter = typeParameter;
|
||||
}
|
||||
|
||||
public int getTypeParameterIndex() {
|
||||
return typeParameter.getIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeNode execute(VirtualFrame frame) {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
@@ -429,4 +437,23 @@ public abstract class UnresolvedTypeNode extends PklNode {
|
||||
return new TypeVariableNode(sourceSection, typeParameter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An unresolved type node that is pre-resolved to a concrete type node. Used during type alias
|
||||
* instantiation to replace type variable references inside constraint expressions (e.g., {@code
|
||||
* every((it) -> it is T)}) with the corresponding concrete type argument.
|
||||
*/
|
||||
public static final class Resolved extends UnresolvedTypeNode {
|
||||
@Child private TypeNode typeNode;
|
||||
|
||||
public Resolved(SourceSection sourceSection, TypeNode typeNode) {
|
||||
super(sourceSection);
|
||||
this.typeNode = typeNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeNode execute(VirtualFrame frame) {
|
||||
return typeNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.oracle.truffle.api.source.SourceSection;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.PType;
|
||||
import org.pkl.core.StackFrame;
|
||||
import org.pkl.core.ValueFormatter;
|
||||
import org.pkl.core.ast.type.TypeNode.UnionTypeNode;
|
||||
@@ -333,4 +334,44 @@ public abstract class VmTypeMismatchException extends ControlFlowException {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Reference extends VmTypeMismatchException {
|
||||
|
||||
private final PType expectedDomainType;
|
||||
private final PType expectedReferentType;
|
||||
|
||||
public Reference(
|
||||
SourceSection sourceSection,
|
||||
VmReference actualValue,
|
||||
PType expectedDomainType,
|
||||
PType expectedReferentType) {
|
||||
super(sourceSection, actualValue);
|
||||
this.expectedDomainType = expectedDomainType;
|
||||
this.expectedReferentType = expectedReferentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildMessage(
|
||||
AnsiStringBuilder builder, String indent, boolean withPowerAssertions) {
|
||||
builder
|
||||
.append(
|
||||
ErrorMessages.createIndented(
|
||||
"typeMismatch",
|
||||
indent,
|
||||
new PType.Class(
|
||||
RefModule.getReferenceClass().export(),
|
||||
expectedDomainType,
|
||||
expectedReferentType),
|
||||
((VmReference) actualValue).exportType()))
|
||||
.append("\n")
|
||||
.append(indent)
|
||||
.append("Value: ")
|
||||
.append(VmValueRenderer.singleLine(80 - indent.length()).render(actualValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean hasHint() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -103,7 +103,7 @@ final class ExternalResourceResolverImpl implements ExternalResourceResolver {
|
||||
readResponses.computeIfAbsent(
|
||||
baseUri,
|
||||
(uri) -> {
|
||||
var future = new CompletableFuture<byte[]>();
|
||||
var future = new CompletableFuture<byte @Nullable []>();
|
||||
var request =
|
||||
new ReadResourceRequest(requestIdGenerator.nextLong(), evaluatorId, uri);
|
||||
try {
|
||||
|
||||
@@ -46,7 +46,6 @@ import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import org.pkl.core.SecurityManagerException;
|
||||
import org.pkl.core.util.ErrorMessages;
|
||||
import org.pkl.core.util.Exceptions;
|
||||
|
||||
@@ -93,7 +92,7 @@ final class JdkHttpClient implements HttpClient {
|
||||
HttpRequest request,
|
||||
BodyHandler<T> responseBodyHandler,
|
||||
HttpRequestChecker httpRequestChecker)
|
||||
throws IOException, SecurityManagerException {
|
||||
throws IOException {
|
||||
try {
|
||||
return underlying.send(request, responseBodyHandler);
|
||||
} catch (ConnectException e) {
|
||||
|
||||
@@ -84,7 +84,7 @@ public final class Messages {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -93,12 +93,14 @@ public class PathElement {
|
||||
}
|
||||
|
||||
/** Returns the element at path {@code basePath}, given a {@link Path}. */
|
||||
@SuppressWarnings("DataFlowIssue") // incorrect analysis; this can return null.
|
||||
public @Nullable TreePathElement getElement(Path basePath) {
|
||||
var path = basePath.normalize();
|
||||
var element = this;
|
||||
for (var i = 0; i < path.getNameCount(); i++) {
|
||||
var part = path.getName(i).toString();
|
||||
element = element.getChildren().get(part);
|
||||
//noinspection ConstantValue
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -183,6 +183,7 @@ public final class ProjectDependenciesManager {
|
||||
public Map<String, Dependency> getLocalPackageDependencies(PackageUri packageUri) {
|
||||
ensureDependenciesInitialized();
|
||||
var dep = localPackageDependencies.get(packageUri);
|
||||
//noinspection ConstantValue
|
||||
assert dep != null;
|
||||
return dep;
|
||||
}
|
||||
|
||||
@@ -53,9 +53,11 @@ public abstract class Dependency {
|
||||
}
|
||||
|
||||
public URI resolveAssetUri(URI projectBaseUri, PackageAssetUri packageAssetUri) {
|
||||
// drop 1 to remove leading `/`
|
||||
var assetPath = packageAssetUri.getAssetPath().substring(1);
|
||||
var resolvedPath = path.resolve(assetPath);
|
||||
// copy how remote dependencies work; the `..` segment at the root just normalizes to the
|
||||
// root.
|
||||
var assetPath = Path.of(packageAssetUri.getAssetPath()).normalize();
|
||||
var relativePath = Path.of("/").relativize(assetPath);
|
||||
var resolvedPath = path.resolve(relativePath);
|
||||
var normalized = IoUtils.toNormalizedPathString(resolvedPath);
|
||||
try {
|
||||
var relativeUri = new URI(null, null, normalized, null);
|
||||
@@ -67,7 +69,7 @@ public abstract class Dependency {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
@@ -107,7 +109,7 @@ public abstract class Dependency {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -217,6 +217,7 @@ public final class DependencyMetadata {
|
||||
var map = new HashMap<>();
|
||||
for (var kv : value) {
|
||||
var kvObj = (JsObject) kv;
|
||||
assert kvObj != null;
|
||||
map.put(parsePObject(kvObj.get("key")), parsePObject(kvObj.get("value")));
|
||||
}
|
||||
return map;
|
||||
@@ -294,7 +295,7 @@ public final class DependencyMetadata {
|
||||
var ret = new ArrayList<String>(arr.size());
|
||||
for (var elem : arr) {
|
||||
if (!(elem instanceof String string)) {
|
||||
throw new FormatException("string", elem.getClass());
|
||||
throw new FormatException("string", elem != null ? elem.getClass() : Void.class);
|
||||
}
|
||||
ret.add(string);
|
||||
}
|
||||
@@ -414,7 +415,7 @@ public final class DependencyMetadata {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
@@ -624,8 +625,8 @@ public final class DependencyMetadata {
|
||||
jsonWriter.endObject();
|
||||
}
|
||||
|
||||
private void writeGenericObject(Object value) throws IOException {
|
||||
if (value instanceof PNull) {
|
||||
private void writeGenericObject(@Nullable Object value) throws IOException {
|
||||
if (value == null || value instanceof PNull) {
|
||||
jsonWriter.nullValue();
|
||||
} else if (value instanceof PObject pObject) {
|
||||
writePObject(pObject);
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.pkl.core.packages;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.PklBugException;
|
||||
import org.pkl.core.Version;
|
||||
import org.pkl.core.util.ErrorMessages;
|
||||
@@ -98,7 +99,7 @@ public final class PackageAssetUri {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import java.util.stream.StreamSupport;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import org.graalvm.collections.EconomicMap;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.PklBugException;
|
||||
import org.pkl.core.SecurityManager;
|
||||
import org.pkl.core.SecurityManagerException;
|
||||
import org.pkl.core.http.HttpClient;
|
||||
@@ -456,10 +457,17 @@ final class PackageResolvers {
|
||||
}
|
||||
|
||||
private Path getRelativePath(PackageUri uri) {
|
||||
return Path.of(
|
||||
var relativePath =
|
||||
Path.of(
|
||||
CACHE_DIR_PREFIX,
|
||||
IoUtils.encodePath(uri.getUri().getAuthority()),
|
||||
getEffectivePackageUriPath(uri));
|
||||
// ensure the derived path cannot escape the cache directory
|
||||
var resolved = cacheDir.resolve(relativePath).normalize();
|
||||
if (!resolved.startsWith(cacheDir.normalize())) {
|
||||
throw new PklBugException("Package URI escapes the cache directory");
|
||||
}
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
private String getLastSegmentName(PackageUri packageUri) {
|
||||
|
||||
@@ -61,6 +61,13 @@ public final class PackageUri {
|
||||
throw new URISyntaxException(
|
||||
uri.toString(), ErrorMessages.create("missingPathInPackageUri", uri));
|
||||
}
|
||||
// reject `..` segments, percent-encoded or not
|
||||
for (var segment : path.split("/", -1)) {
|
||||
if (segment.equals("..")) {
|
||||
throw new URISyntaxException(
|
||||
uri.toString(), ErrorMessages.create("invalidRelativePathInPackageUri"));
|
||||
}
|
||||
}
|
||||
var versionIdx = path.lastIndexOf('@');
|
||||
if (versionIdx == -1) {
|
||||
throw new URISyntaxException(
|
||||
@@ -111,7 +118,7 @@ public final class PackageUri {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 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,6 +17,7 @@ package org.pkl.core.project;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.PklBugException;
|
||||
import org.pkl.core.packages.PackageUri;
|
||||
import org.pkl.core.util.ErrorMessages;
|
||||
@@ -84,7 +85,7 @@ public record CanonicalPackageUri(URI baseUri, int majorVersion) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ public final class Project {
|
||||
sb.append("\n│");
|
||||
}
|
||||
sb.append("\n│ ");
|
||||
sb.append(uri.toString());
|
||||
sb.append(uri);
|
||||
}
|
||||
sb.append("\n└─");
|
||||
}
|
||||
@@ -477,7 +477,7 @@ public final class Project {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
@@ -611,7 +611,7 @@ public final class Project {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ public final class ProjectDependenciesResolver {
|
||||
private void updateDependency(Dependency dependency) {
|
||||
var canonicalPackageUri = CanonicalPackageUri.fromPackageUri(dependency.getPackageUri());
|
||||
var currentDependency = resolvedDependencies.get(canonicalPackageUri);
|
||||
//noinspection ConstantValue
|
||||
if (currentDependency == null
|
||||
|| currentDependency.getVersion().compareTo(dependency.getVersion()) < 0) {
|
||||
EconomicMaps.put(resolvedDependencies, canonicalPackageUri, dependency);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user