Skip to content

Add nullability support for server parameter delegation#5486

Open
nomisRev wants to merge 2 commits intomainfrom
nomisrev/nullable-parameter-delegation
Open

Add nullability support for server parameter delegation#5486
nomisRev wants to merge 2 commits intomainfrom
nomisrev/nullable-parameter-delegation

Conversation

@nomisRev
Copy link
Copy Markdown
Contributor

Subsystem
Server, core

Motivation
Currently it is not possible to use nullable values with parameter delegation.

get("/nullable") {
    val nameOrNull: String? by call.queryParameters
    val ageOrNull: Int? by parameters
}

Solution

This PR add support by removing the : Any constraint and relying on typeInfo.kotlinType?.isMarkedNullable to check if null is allowed or not.

@nomisRev nomisRev requested review from bjhham, e5l and osipxd March 20, 2026 09:37
@nomisRev
Copy link
Copy Markdown
Contributor Author

I'm a bit unsure how reliable typeInfo.kotlinType?.isMarkedNullable is across platforms?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e0610b9a-2abc-4ef8-a8f8-deab6e4b869b

📥 Commits

Reviewing files that changed from the base of the PR and between 86d7c3f and 1056631.

📒 Files selected for processing (1)
  • ktor-server/ktor-server-core/common/src/io/ktor/server/util/Parameters.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • ktor-server/ktor-server-core/common/src/io/ktor/server/util/Parameters.kt

📝 Walkthrough

Walkthrough

Generic type constraints for Parameters delegated accessors were relaxed to allow nullable result types; implementation now returns null for absent parameters when the target type is nullable and preserves existing exceptions for non-nullable types and conversion failures.

Changes

Cohort / File(s) Summary
API Signatures
ktor-server/ktor-server-core/api/ktor-server-core.klib.api
Adjusted exported signatures: getOrFailImpl and getValue type parameter bounds changed from A: Any to A: Any? (nullable-capable generics).
Core Implementation
ktor-server/ktor-server-core/common/src/io/ktor/server/util/Parameters.kt
Removed non-null constraint on R for getValue and getOrFail; getOrFailImpl now checks typeInfo.kotlinType?.isMarkedNullable and returns null as R when appropriate, otherwise throws MissingRequestParameterException or ParameterConversionException as before. KDoc and expression-bodied forms updated.
Tests
ktor-server/ktor-server-core/common/test/io/ktor/server/http/ParametersTest.kt
Added tests covering nullable delegated properties resolving to value or null, conversion failure for nullable target, and missing non-null delegated value throwing MissingRequestParameterException.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding nullability support for server parameter delegation, which is the core objective of the PR.
Description check ✅ Passed The description covers all required template sections with relevant detail: subsystem (Server, core), motivation (inability to use nullable values with delegation), and solution (removing : Any constraint and checking nullability).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch nomisrev/nullable-parameter-delegation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@bjhham bjhham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like an easy win 👍

I'm pretty sure isMarkedNullable works cross-platform on reified KTypes.

I don't know why we didn't just implement it that way in the first place...

@bjhham
Copy link
Copy Markdown
Contributor

bjhham commented Mar 20, 2026

FYI logged an issue to handle property delegation in the compiler plugin:
KTOR-9422 OpenAPI code inference misses property delegation

Copy link
Copy Markdown
Member

@e5l e5l left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

…getOrFailImpl`.

This way both `getOrFail` and `getValue` now support nullable types.
@nomisRev
Copy link
Copy Markdown
Contributor Author

nomisRev commented Apr 1, 2026

@osipxd I updated the PR to move the nullability check in the actual implementation. This way we now also support nullable types for getOrFail.

TypeInfo is always being created because it's used by the underlying conversions mechanism. Perhaps the conversions mechanism can be optimised to avoid TypeInfo where possible but I left that for outside of this scope since it seems unrelated to my changes.

Could you review again? Thank you for the careful review and pointing it out! 🙏 We're still getting a better outcome thanks to it!

} catch (cause: Exception) {
throw ParameterConversionException(name, typeInfo.type.simpleName ?: typeInfo.type.toString(), cause)
internal fun <R> Parameters.getOrFailImpl(name: String, typeInfo: TypeInfo): R {
return if (typeInfo.kotlinType?.isMarkedNullable == true && get(property.name) == null) {
Copy link
Copy Markdown
Member

@osipxd osipxd Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for updating the PR!
Only one thing I've noticed. Compilation fails here: ‎property is unresolved in this scope (probably should be ‎name) 👀

Copy link
Copy Markdown
Contributor Author

@nomisRev nomisRev Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sorry about that! I was coding without loading the project 😅 Takes too much resources 💀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants