Code action: convert type to module#532
Code action: convert type to module#532aspeddro wants to merge 9 commits intorescript-lang:masterfrom
Conversation
zth
left a comment
There was a problem hiding this comment.
Awesome! 😄 I'll let @cristianoc look at the OCaml parts more in depth. I noticed there's a few refactors - might be good to add a comment for each of those and detail what they do/why.
| | Some newExpr -> | ||
| let range = rangeOfLoc newExpr.pexp_loc in | ||
| let newText = printExpr ~range newExpr in | ||
| let uri = Uri.fromPath path |> Uri.toString in |
There was a problem hiding this comment.
To return uri scheme.
There was a problem hiding this comment.
Forgot why this does not just return the string it starts with?
There was a problem hiding this comment.
Was breaking code actions in neovim client because it was not returning uri scheme from LSP spec.
[{"title": "Add type annotation", "kind": "refactor.rewrite", "edit": {"documentChanges": [{
"textDocument": {
"version": null,
"uri": "/home/pedro/Desktop/learning-rescript/src/intro/Codeaction.res"
},
"edits": [{
"range": {"start": {"line": 20, "character": 5}, "end": {"line": 20, "character": 5}},
"newText": ": int"
}]
}]}}]In vscode it works without problem
There was a problem hiding this comment.
Sorry what I meant to ask is: what does this composition of functions do?
Let's put it into a single function with a name suggesting what it does, and use that function instead. So it's less likely that the same issue will pop up somewhere else by copy paste and change in future.
|
Haven't looked at the ocaml code that -- can do that soon. The questions that immediately come to mind are: is this too narrow a use case? Or is it general enough? So my question at the moment is: should we worry about these aspects already? Or just experiment first with a few features see how they feel and how they are used, knowing we might revise perhaps even heavily later? |
|
Also, should we have an inverse action? To move something out of a module? |
|
Some usage questions: this does not seem to trigger an action: type rec tree = Node({name: string, leaves: leaves}) | Empty
and leaves = {number: int, entries: array<tree>} |
|
|
|
|
|
Just as a simple test. Before: type myType = This | That
let fun1 = (x: myType) => x
let fun2 = b => b ? This : ThatOhhh I was surprised to see that half of this is done automatically already: module MyType = {
type t = This | That
}
let fun1 = (x: MyType.t) => x
let fun2 = b => b ? This : ThatWhat's left is the final step: module MyType = {
type t = This | That
}
let fun1 = (x: MyType.t) => x
let fun2 = b => b ? MyType.This : ThatAnd one might or might not want to try to automate the final step. |
|
Naming: should this be called "move type definition into its own module"? |
|
Now support variant/record/object type state = New | Unread | Read
type refState = state
type person = {"age": int, "name": string}
type user = {
name: string,
age: int,
}
and response = Yes | No
type myType = This | That
let fun1 = (x: myType) => x
let fun2 = b => b ? This : That
let fun3 = b => b ? {name: "Lhs", age: 2} : {name: "Rhs", age: 3}
let fun4 = b => b ? Yes : No
let me: person = {
"age": 5,
"name": "Big ReScript",
}module State = {
type t = New | Unread | Read
}
module RefState = {
type t = State.t
}
module Person = {
type t = {"age": int, "name": string}
}
module User = {
type t = {
name: string,
age: int,
}
and response = Yes | No
}
module MyType = {
type t = This | That
}
let fun1 = (x: MyType.t) => x
let fun2 = b => b ? MyType.This : That
let fun3 = b => b ? {User.name: "Lhs", age: 2} : {User.name: "Rhs", age: 3}
let fun4 = b => b ? User.Yes : No
let me: Person.t = {
"age": 5,
"name": "Big ReScript",
} |
|
Looks like this is making steady progress. |
|
I haven't forgotten about the high level questions @cristianoc , will get back with them soon. |
|
Here are a few thoughts from me:
Thoughts? |
|
Agreed. |
Yes, I agree. And I only really mean using t as the main type of a module. Anyways, with that said I think going ahead with this would be nice. Again, we can always call it experimental to start with. |
|
Great. Let's move on with this. |
|
|
cristianoc
left a comment
There was a problem hiding this comment.
This looks great.
Left some comments, nothing substantial.
There's a "ready for review" comment deleted so not sure if more changes are planned.
|
|
||
| let xform ~path ~pos ~codeActions ~printStructureItem structure ~debug = | ||
| let result = ref None in | ||
| let newTypeName = "t" in |
There was a problem hiding this comment.
Feels like this logic should be factored out into its own easy to modify little local module.
| | Some (newStructureItem, references, modName) -> | ||
| let range = rangeOfLoc newStructureItem.pstr_loc in | ||
| let newText = printStructureItem ~range newStructureItem in | ||
| let uri = Uri.fromPath path |> Uri.toString in |
There was a problem hiding this comment.
Another instance of this.
If this does something useful, it should probably be moved into a standalone function inside Uri.
| AddTypeAnnotation.xform ~path ~pos ~full ~structure ~codeActions ~debug; | ||
| IfThenElse.xform ~pos ~codeActions ~printExpr ~path structure; | ||
| AddBracesToFn.xform ~pos ~codeActions ~path ~printStructureItem structure; | ||
| TypeToModule.xform ~path ~pos ~codeActions ~printStructureItem structure |
There was a problem hiding this comment.
We have quite a few of these.
Need a little sanity check:
- that they don't do repeat work in a way that hurts perf (iterating several times is probably ok while copying would not)
- that no work is done unless the action fires
This is just about reviewing the code and check that things are OK.
|
It will take some time to get ready. There are more cases I need to check. |

Add basic support to convert type to module.
Current state:
TODO:
Demo:
screencast-2022-07-29_20.43.26.mp4
Close #430