Skip to content
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

[Proposal] Pipeline hints #2074

Open
KennethHoff opened this issue Dec 20, 2024 · 2 comments
Open

[Proposal] Pipeline hints #2074

KennethHoff opened this issue Dec 20, 2024 · 2 comments

Comments

@KennethHoff
Copy link

KennethHoff commented Dec 20, 2024

Pipeline hints

Problem

F#, and I'm sure other languages, heavily utilizes pipelining/chaining of function calls. Such pipelines can at times make knowing types quite difficult, particularly if you're unfamiliar with the domain.

F#

let input = System.IO.File.ReadAllLines("day1.txt")

input
|> Array.map Utils.splitStringIntoPair
|> Array.map Utils.convertStringPairToIntPair
|> Array.unzip
|> Utils.sortTupleElements
|-> Array.zip
|> Array.map Utils.abs
|> Array.sum
|> Taps.logAndContinue "Part 1: %d"

Fluent APIs have become much more common lately, with things like Zod being used in the JavaScript ecosystem for typesafe validation, and ASP.Net Core utilizing it heavily with their entrypoint file, the need for IntelliSense on these implicit return types are becoming increasingly more common.

C#

WebApplicationBuilder builder = WebApplication.CreateSlimBuilder(args);
builder.Services
    .AddSingleton<TimeProvider>(TimeProvider.System)
    .AddScoped<IPersonService, PersonService>()

WebApplication app = builder.Build();

app
    .MapGet("/api/person/{id}" (Guid id) => { /* Logic here */  })
    .WithDescription("Retrieves the person with the given id")

app.Run();

Proposal

I'm suggesting a new request designed to highlight return types of function calls whose values are implicitly passed to another function. This will help solve both of the previous problem statements.

I am not well versed enough in the intricate details of the LSP request specification to come up with anything more detailed than these visual examples, so at the moment I'm mostly interrested in starting a discussion; The request specification can come at a later date.

(Imagine that the code in the comments are the hints provided by the LSP, and not code comments)

F#

let input = System.IO.File.ReadAllLines("day1.txt")

input
|> Array.map Utils.splitStringIntoPair // (string * string) array
|> Array.map Utils.convertStringPairToIntPair // (int * int) array
|> Array.unzip // (int array) * (int array)
|> Utils.sortTupleElements // (int array) * (int array)
|-> Array.zip // (int * int) array
|> Array.map Utils.abs // int array
|> Array.sum // int
|> Taps.logAndContinue "Part 1: %d" // int

C#

WebApplicationBuilder builder = WebApplication.CreateSlimBuilder(args);
builder.Services
    .AddSingleton<TimeProvider>(TimeProvider.System) // IServiceCollection
    .AddScoped<IPersonService, PersonService>() // IServiceCollection

WebApplication app = builder.Build();

app
    .MapGet("/api/person/{id}" (Guid id) => { /* Logic here */  }) // RouteHandlerBuilder
    .WithDescription("Retrieves the person with the given id") // RouteHandlerBuilder

app.Run();

Alternatives

Extend the existing inlayHints request instead of creating a new one. This has the advantage of not requiring an entirely new request type, but the downside of polluting the inlayHints request, as well as any possible breaking changes to make it more ergonomic for this need.

Potentially relevant information

The naming is based off of Ionide (The F# LSP), which has their own custom fsharp-specific request with the same name, and has implemented it in their Visual Studio Code Plugin, but has not done so in their Neovim plugin, due to lack of support in Neovim.

@HighCommander4
Copy link

rust-analyzer supports this today, using inlay hints. Here is an example:

Image

Doing it this way doesn't really require a protocol extension; while the protocol defines an InlayHintKind enum with two values (Type and Parameter), neither of which are applicable here, the kind field of InlayHint in the protocol is optional, which seems to give license to servers to send inlay hints of other kinds.

(Clangd is another server that supports inlay hint kinds beyond the two defined in the protocol, though pipeline hints are not one of them at this time.)

@KennethHoff
Copy link
Author

I did not realize InlayHintKind existed; That changes things. It does sound like that should be extended in favor of adding a new request type type that is essentially the same thing.

The concept is very similar to a type hint, so much so that one could argue it should use InlayHintKind.Type already, but it probably shouldn't as it's presumably not designed for this use-case.

Adding a InlayHintKind.Pipeline ( name TBD) would therefore seemingly be a much better alternative than an entirely new request type.

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

No branches or pull requests

2 participants