-
Notifications
You must be signed in to change notification settings - Fork 57
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
Code action: convert type to module #532
base: master
Are you sure you want to change the base?
Code action: convert type to module #532
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
@@ -110,9 +110,20 @@ module IfThenElse = struct | |||
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To return uri
scheme.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot why this does not just return the string it starts with?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 : That Ohhh 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 : That What's left is the final step: module MyType = {
type t = This | That
}
let fun1 = (x: MyType.t) => x
let fun2 = b => b ? MyType.This : That And 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. |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another instance of this.
If this does something useful, it should probably be moved into a standalone function inside Uri.
@@ -310,5 +462,7 @@ let extractCodeActions ~path ~pos ~currentFile ~debug = | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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