Skip to content

Conversation

zth
Copy link
Member

@zth zth commented Dec 16, 2022

This adds completion for pipe chains, without requiring compilation, when the return type can be inferred for the current pipe chain.

Example:

let arr = [1, 2, 3]

// Everything below is without saving (without compilation)
let _ = arr->
//           ^ this already completed to Js.Array2 before

let _ = arr->Js.Array2.map(v => v)->
//                                  ^ but this didn't. It does now, as we complete from the last expression before the final pipe (Js.Array2.map in this case)

It handles when the return type is known without having to infer type parameters. Next step would be to handle inferring via type parameters too, but that's a vastly larger thing.

This however should make a lot of workflows more convenient, even in its current state.

@zth zth requested a review from cristianoc December 16, 2022 19:48
@zth
Copy link
Member Author

zth commented Dec 17, 2022

Side note (and not something to solve in this PR per se) - it would be interesting to figure out why pipe completion doesn't work after reduce in the example below, even after compiling:

let extractDeps = rawDeps =>
  rawDeps
  ->String.split(" ")
  ->Array.map(s => (s->String.trim->Path.parse).name)
  ->Array.reduce([], (acc, curr) => {
    if acc->Array.includes(curr) {
      acc
    } else {
      let _ = acc->Array.push(curr)
      acc
    }
  })

@@ -0,0 +1,1970 @@
Complete src/CompletionPipeChain.res 2:16
posCursor:[2:16] posNoWhite:[2:15] Found expr:[2:11->0:-1]
Completable: Cpath Value[arr]->
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you change the test so the results are 1 or 2 entries? (e.g. define your own little module)
What's going on is drowned in a sea of results.

@cristianoc
Copy link
Collaborator

cristianoc commented Dec 17, 2022

I think a concise description of what this does is:

  • Complete e->id-> as if it were id(e)->
  • Complete e->foo(a,b)-> as if it were foo(e,a,b)->

so this is teaching completion the semantics of pipe.
Correct?

@zth
Copy link
Member Author

zth commented Dec 17, 2022

Correct.

@cristianoc
Copy link
Collaborator

Side note (and not something to solve in this PR per se) - it would be interesting to figure out why pipe completion doesn't work after reduce in the example below, even after compiling:

let extractDeps = rawDeps =>
  rawDeps
  ->String.split(" ")
  ->Array.map(s => (s->String.trim->Path.parse).name)
  ->Array.reduce([], (acc, curr) => {
    if acc->Array.includes(curr) {
      acc
    } else {
      let _ = acc->Array.push(curr)
      acc
    }
  })

For the same reason that this does not work:

let id = x=>x

let e = id([])->

but this does:

let idArray = (x:array<_>)=> x

let e = idArray([])->

Namely, completion for application takes the result type. And without typing the not-yet-compiled code, one cannot deduce the return type of the function. And gets the declared type instead ('a).

@zth
Copy link
Member Author

zth commented Dec 17, 2022

This is with compiling though. That should make a difference, right?

@cristianoc
Copy link
Collaborator

This is with compiling though. That should make a difference, right?

You can't compile incomplete code.
Even if you successfully compile this:

let e = id([])

it does not mean you know the type of id([]) in general. It only means you know the type of e is an array.

So when you then do this:

let e = id([])->

it really does not help to know that something called e was an array last time you compiled.

@zth zth merged commit 2a6ce8c into master Dec 21, 2022
@zth zth deleted the complete-pipe-chain branch December 21, 2022 20:39
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.

2 participants