Changes:
- Update wrapper by running the following command:
./gradlew wrapper --gradle-version 8.11 --gradle-distribution-sha256-sum
57dafb5c2622c6cc08b993c85b7c06956a2f53536432a30ead46166dbca0f1e9
- Verify wrapper JAR integrity according to:
https://docs.gradle.org/current/userguide/gradle_wrapper.html#
manually_verifying_the_gradle_wrapper_jar
- Replace usages of deprecated method `Project.exec` with `ExecOperations.exec`
- Convert extension function `Task.configureInstallGraalVm` to task class `InstallGraalVm`
- a task class is the cleanest way to get hold of `ExecOperations`
- Move extension property `BuildInfo.GraalVm.downloadFile` into class `GraalVm`
- Don't apply plugin `pklGraalVm` in project `bench` (unnecessary, now causes error)
The new name is consistent with existing names JavaCodeGenerator and CliJavaCodeGeneratorOptions.
Backward compatibility is ensured by turning JavaCodegenOptions into a (deprecated) type alias.
Also: deprecate `CliJavaCodeGeneratorOptions.toJavaCodegenOptions()`
codegen-java:
- use `pattern.pattern()` instead of `pattern` in hashCode method
(consistent with equals method)
codegen-kotlin:
- use `regex.pattern` instead of `regex` in hashCode method
(consistent with equals method)
- if a data class has a Regex property, generate not only
an equals method but also a hashCode method
Motivation:
codegen-kotlin generates a mix of data classes and regular classes.
For regular classes, toString() methods are also generated.
However, the output of generated toString() methods
differs from the output of default toString() methods of data classes.
Changes:
Generate toString() methods that produce the same output
as default toString() methods of data classes.
Also: rename KotlinCodegenOptions to KotlinCodeGeneratorOptions
The new name is consistent with existing names KotlinCodeGenerator and CliKotlinCodeGeneratorOptions.
Backward compatibility is ensured by turning KotlinCodegenOptions into a (deprecated) type alias.
Motivation:
The following expression evaluates to 2 instead of 1:
new Listing { "value" } { [0 + 0] = "override" }.length
Changes:
- fix length computation in EntriesLiteralNode
- improve `api/listing` tests
- make snippet test failures diffable in IntelliJ
Result:
- fixes https://github.com/apple/pkl/issues/780
- improved dev experience in IntelliJ
- change line numbers from blue to faint to improve legibility on dark backgrounds
- use EnumSet throughout
- move all ANSI classes into package core.util (no need to split them over util and runtime)
- rename AnsiCodingStringBuilder to AnsiStringBuilder
GraalVM for JDK 17.0.12 is the final Critical Patch Update
made available under the GraalVM Free Terms and Conditions license.
Subsequent Critical Patch Updates require a commercial license.
- keep implementation classes internal to their packages
- make classes final if possible
- make namespace classes non-instantiable
- throw IllegalStateException instead of ExternalReaderProcessException for use after close
- common convention already used by HttpClient etc.
- programming errors should be signaled with unchecked exceptions
- use private instead of public lock object
- polish Javadoc
- delete commented out code
- don't use star import for a single class
Motivation:
In Spring Boot 3.0, the annotation type `org.springframework.boot.context.properties.ConstructorBinding`
was deprecated in favor of `org.springframework.boot.context.properties.bind.ConstructorBinding`.
In 3.2, the old annotation type was removed.
As of 3.0, a `@ConstructorBinding` annotation is no longer required/recommended for configuration classes with a single public constructor.
Changes:
Remove generation of `@ConstructorBinding` annotations in codegen-java and codegen-kotlin.
Result:
- Generated code is compatible with Spring Boot 3.x.
(Verified with locally updated pkl-spring.)
- Generated code is no longer compatible with Spring Boot 2.x.
To use Pkl 0.27 and later with Spring Boot 2.x, use Pkl 0.26's code generator.
- Fixes#139.
Motivation:
- Java serialization makes as much sense for module classes as it does for regular classes.
- Offer same Java serialization support as codegen-java.
Changes:
- Move generation of `appendProperty` method and serialization code
into new method `generateCompanionRelatedCode`.
- Improve/fix generation of serialization code.
Result:
Java serialization is also supported for module classes.
Motivation:
Currently, the condition for making a generated Java class instantiable is "class is neither abstract nor stateless".
(An instantiable class receives a public constructor and equals/hashCode/toString/with methods.)
This is inconsistent with Pkl and codegen-kotlin, both of which support instantiation of stateless classes.
Changes:
Widen condition for making a class instantiable to "class is neither abstract nor a stateless final module class".
This is consistent with codegen-kotlin, which generates object declarations (only) for stateless final module classes.
Result:
Stateless classes are instantiable in Pkl, codegen-java, and codegen-kotlin.
Motivation:
- Currently, the condition for generating equals/hashCode/toString methods is "generated class declares properties".
As a result, classes that don't declare properties inherit these methods from their generated superclasses.
However, generated `equals` and `toString` methods aren't designed to be inherited
and will either fail or produce wrong results when called for a subclass.
- Currently, the condition for generating `with` methods is "class is not abstract".
However, it isn't useful to generate `with` methods for non-instantiable non-abstract classes.
- Currently, the condition for making classes serializable is "class is not a module class".
However, it isn't useful to make non-instantiable non-module classes serializable,
and it is useful to make instantiable module classes serializable.
Changes:
- Change condition for generating equals/hashCode/toString/with/Serializable to "class is instantiable".
This is a breaking change.
(A generated class is instantiable, i.e., declares a public constructor,
if it is neither abstract nor stateless. This behavior remains unchanged for now.)
- Overhaul JavaCodeGeneratorTest
- introduce classes JavaSourceCode and JavaSourceCodeAssert
- change assertions to use JavaSourceCodeAssert via `assertThat(javaCode)`
- use parameterized test instead of loop
- use explicit trimIndent() and trimMargin() for multiline string literals
- IntelliJ editor desperately wants to insert trimIndent()
- can potentially be exploited by kotlinc and ktfmt
Result:
- Fixes all motivating issues.
- Fixes#706.
* codegen-kotlin: Don't generate equals/hashCode/toString/copy/:Serializable for abstract classes
* Polish KotlinCodeGeneratorTest
- use `assertContains()` instead of `assertThat().contains()`
- remove redundant `trimIndent()` and `trimMargin()` calls
- rename `javaCode` to `kotlinCode`
* Overhaul KotlinCodeGeneratorTest
- introduce classes KotlinSourceCode and KotlinSourceCodeAssert
- change assertions to use KotlinSourceCodeAssert via `assertThat(kotlinCode)`
- use explicit trimIndent() and trimMargin() for multiline string literals
- IntelliJ editor desperately wants to insert trimIndent()
- can be used by kotlinc and ktfmt
- format code in the exact way it falls out of the IntelliJ editor
(successfully destroyed by ktfmt)
- Update dependencies by deleting lock files and regenerating them with `gw updateDependencyLocks`.
Deleting lock files avoids strange `some.library:some.older.version=default` entries.
Most updated dependencies are test dependencies.
- Handle breaking changes in library commonmark.
- Fix test to close PackageServer exactly once.
This problem surfaced because JUnit 5.11 changed override rules for lifecycle methods,
resulting in too many instead of too few close() calls.
- Bump msgpack version
- Bump clikt version
- Bump Gradle plugin versions
Motivation:
Speed up the test that verifies enforcement of the limit for glob pattern resolution (invalidGlobImport6.pkl).
Changes:
- Set a lower limit if test mode is enabled.
- Change static field to static method to prevent compile-time evaluation by native-image.
* Split MemberNode into (Regular/Shared)MemberNode
SharedMemberNode enables generating non-constant object members
at run time without generating an unbounded number of Truffle root nodes.
* Invert shouldRunTypeCheck to match its name
* Introduce VmObjectBuilder
Introduce VmObjectBuilder, a uniform way to build `VmObject`s
whose `ObjectMember`s are determined at run time.
Replace some manual object building code with VmObjectBuilder.
Add some assertions to fix IntelliJ warnings.
* Improve implementation of globbed read/import nodes
- Leverage SharedMemberNode to have a single Truffle root node per globbed
read/import expression instead of one root node per resolved glob element.
- Remove caching in ReadGlobNode because it only works correctly if glob pattern is a string *constant*.
- Remove caching in StaticReadNode (now ReadGlobElementNode/ImportGlobElementNode)
because it seems unnecessary and the implementation doesn't look quite right.
* Simplify code
* Fix ClassCastException when reflecting on globbed import
* Fix caching of globbed reads
Problem:
The result of a globbed read depends not only on the glob pattern but also on the current module URI.
However, ResourceManager does not take this into account when caching globbed reads, causing wrong results.
Changes:
- Cache globbed reads per read expression.
This is also how globbed imports are cached, except that import URIs are constant.
- Make ReadGlobNode and ImportGlobNode code as similar as possible.
- Reduce code duplication by inheriting from AbstractReadNode.
- Add some tests.
Fix all IntelliJ warnings in Java production code except for
bogus spelling warnings and warnings about unused public methods.
Also fix some warnings emitted by Code->Inspect Code.
Changes made:
- use text block instead of string concatenation
- extract method to avoid code duplication
- use switch expression
- fix Javadoc syntax and spelling
- fix spelling in comment
- increase class visibility to match visibility of use site
- delete overriding method with same implementation
- use String.isEmpty() and StringBuilder.isEmpty()
- add @Serial annotation
- make field final
- remove unused field
- remove unused private method
- remove exceptions that aren't thrown from throws clause
- insert non-null assertion
- annotate overriding method with @Nonnull
- suppress warning
- delete unused class (WriteAuxiliarySlotNode)
- add final modifier
- remove unused error message
- repeat @Nullable modifier in overriding method
- remove never thrown exception from throws clause
- remove redundant suppression
- Refactor code to use the following basic Java 17 features:
- pattern matching for instanceof
- @Serial annotation
- switch expressions
- enhanced switch statements
- StringBuilder.isEmpty()
- Replace two switch statements with simpler if statements.
- Rename a few local variables.
- Check `method.isConst()` every time a method is resolved
instead of once per node instance (`isConstChecked`).
Given that `needsConst` only happens in very specific circumstances,
I'm not entirely sure if every resolved method needs to be checked.
However, it's a cleaner solution in any case, and `method.isConst()`
is a fast check that also never happens on the `evalCached` fast path.
- Do not check for const-ness of `FunctionN.apply` methods.
This check seems unnecessary and would always fail if triggered.
(According to `base.pkl`, none of the `FunctionN.apply` methods is const.)
- Remove unnecessary Truffle boundaries for modifier checks,
which are just bitwise operations.
- Improve const/import docs.
- Update google-java-format to a version compatible with JDK 21 and run "gw spotlessApply".
- Fix wrong test assumption
JavaCodeGenerator writes a properties file using java.util.Properties,
which doesn't guarantee order of entries.
- Fix most deprecation warnings
- Add CI job for JDK 21
Rationale: "Output file names are known only after execution"
isn't a legitimate reason to make this task untracked
because the output directory is known in this case.
This is no different from (say) the `JavaCompile` task,
where only the class file output directory is known upfront.
Forum discussion didn't reveal another reason why this task
should be untracked.
Motivation:
The standard library docs are some of the most important docs
but currently very hard to find. I've noticed that even advanced
users have never heard of them and complain about "zero docs".
Use `Files.newInputStream(path)` instead of `new FileInputStream(path.toFile())`
and `Files.newOutputStream(path)` instead of `new FileOutputStream(path.toFile())`.
- Change HttpClient to follow all redirects except HTTPS to HTTP.
- Run language snippet tests with --no-cache and real PackageServer
instead of pre-seeded cache.
This increases HTTP test coverage and enables testing of package redirects.
- Change PackageServer to return 301 for request paths starting with /HTTP301/
and 307 for request paths starting with /HTTP307/.
- Update some outdated test package checksums that apparently weren't verified.
Make sure that declaring a dependency on project `pkl-commons-test`
suffices to have its test fixtures generated.
This fix should work reliably.
However, there may be a more idiomatic way to achieve the same result.
- Fix and clean up the pkl-commons-test build script.
- Change tests to read test packages/certs directly from
the file system instead of packaging and reading them
from the class path.
- Update expected checksums of some test packages.
- Fix a conflict between Pkl's and Gradle's
Kotlin libraries in the pkl-gradle project.
- Fix build deprecation warnings.
- Ensure Gradle distribution integrity with `distributionSha256Sum`.
- Manually verify integrity of Gradle wrapper added by this commit.
This is a comprehensive solution to the "flaky PackageServer tests"
problem. It rules out port conflicts and imposes no limits on test
parallelism. The same solution can be used for other test servers
in the future.
Major changes:
- Turn `PackageServer` from a singleton into a class that is
instantiated per test class or test method.
- Start the server the first time its `port` property is read.
Bind the server to an ephemeral port instead of port 12110.
- For every test that uses `PackageServer`, pass the server port to
`--test-port`, `HttpClient.Builder.setTestPort`, the `CliBaseOptions`
or `ExecutorOptions` constructor, or the Gradle plugin's `testPort` property.
Wire all of these to `RequestRewritingClient`'s `testPort` constructor parameter.
- Enhance `RequestRewritingClient` to replace port 12110 with `testPort`
in request URIs unless `testPort` is -1 (its default).
- Introduce `ExecutorOptions.Builder`.
This makes executor options more comfortable to create
and allows to hide options such as `testPort`.
- Deprecate the `ExecutorOptions` constructor to steer users towards the builder.
- Get rid of `ExecutorOptions2`, which is no longer needed.
- Clean up `EmbeddedExecutorTest` with the help of the builder.
Moving to java.net.http.HttpClient brings many benefits, including
HTTP/2 support and the ability to make asynchronous requests.
Major additions and changes:
- Introduce a lightweight org.pkl.core.http.HttpClient API.
This keeps some flexibility and allows to enforce behavior
such as setting the User-Agent header.
- Provide an implementation that delegates to java.net.http.HttpClient.
- Use HttpClient for all HTTP(s) requests across the codebase.
This required adding an HttpClient parameter to constructors and
factory methods of multiple classes, some of which are public APIs.
- Manage CA certificates per HTTP client instead of per JVM.
This makes it unnecessary to set JVM-wide system/security properties
and default SSLSocketFactory's.
- Add executor v2 options to the executor SPI
- Add pkl-certs as a new artifact, and remove certs from pkl-commons-cli artifact
Each HTTP client maintains its own connection pool and SSLContext.
For efficiency reasons, It's best to reuse clients whenever feasible.
To avoid memory leaks, clients are not stored in static fields.
HTTP clients are expensive to create. For this reason,
EvaluatorBuilder defaults to a "lazy" client that creates the underlying
java.net.http.HttpClient on the first send (which may never happen).
When I delete pkl-core/src/test/files/LanguageSnippetTests/output and
run "gw test", most output files are regenerated, but 46 of them aren't.
I assume these are stale files that should be deleted.
This improves the development experience for (WSL) Linux users.
They can now run "./gradlew buildNative" without having a musl toolchain installed.
In this case, only the dynamically linked executable will be built.