-
-
Notifications
You must be signed in to change notification settings - Fork 777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LSP code action: generate dynamic decoder #2955
Comments
It could be nice to have two separate code actions for this? One to have a decodeN, which would fail if there were too many arguments for the constructor, and another to generate an inline decoder. When writing my own inline decoders for constructors with 10+ arguments, I had to copy the fn all_errors(result: Result(a, List(DecodeError))) -> List(DecodeError) {
case result {
Ok(_) -> []
Error(errors) -> errors
}
} When I first encountered this, I thought this would 100% be worth adding to the pub fn all_errors(result: Result(a, List(b))) -> List(b) {
case result {
Ok(_) -> []
Error(errors) -> errors
}
} If we did want to generate an in-line decoder for 10+ fields, then instead of having to copy this function, it could just be imported from the standard library. |
I'd like us to have some recommendation for how to implement decoders of unbounded size prior to having a code generator for that, and I'd like to have one action rather than 2 as there should only ever be one recommended way of doing something, and the programmer may not know which option to pick. |
Now that the new decoder API has been merged into the stdlib, I'm happy to work on this. I have a few questions regarding how this should work. Mainly for Louis to answer, but anyone is free to chime in with their opinion.
I've written an example type with all of the above edge-cases. If we can figure out exactly what the LSP should generate for it, then that will give me a comprehensive idea of what I have to do /// What does the decoder for this type look like?
pub type Wibble(value, phantom) {
Wibble(counter: Int, values: List(value), next: Wibble(value, phantom))
Wobble(message: option.Option(String), something_custom: OtherType)
}
// This could be anything
pub type OtherType {
OtherType(Int)
} |
Currently, I'm thinking the above type could generate a function like this: pub fn decode_wibble(
dynamic: dynamic.Dynamic,
value_decoder: decode.Decoder(value),
) -> Result(Wibble(value, phantom), List(decode.DecodeError)) {
let wibble_decoder = {
use counter <- decode.field("counter", decode.int)
use values <- decode.field("values", decode.list(value_decoder))
use next <- decode.field("next", todo as "Decoder for Wibble")
decode.success(Wibble(counter:, values:, next:))
}
let wobble_decoder = {
use message <- decode.field("message", decode.optional(decode.string))
use something_custom <- decode.field(
"something_custom",
todo as "Decoder for OtherType",
)
decode.success(Wobble(message:, something_custom:))
}
decode.run(dynamic, decode.one_of(wibble_decoder, [wobble_decoder]))
} This is currently missing:
|
The header sounds good to me.
We could insert
Let's not support this in the first version.
A private function that returns |
Ok, that sounds good to me. I'll get implementing |
Thank you! |
Oh and one more thing, how do we generate a decoder for a type with unnamed fields? I'm not really sure how that would be represented. |
Let's not offer it for them. The aim isn't to generate decoders for the actual Gleam representation of these types, it's for generating the decoders folks likely want to use them for, which will probably be used with JSON. |
Great, thanks |
We need to decide what the recommendation is for constructors with too many fields for the decodeN functions. Perhaps we can not support them for this first version.
We also need to decide what to do for contained types we don't know the decoder for. Perhaps we can add a
todo as "..."
for now.The text was updated successfully, but these errors were encountered: