-
Notifications
You must be signed in to change notification settings - Fork 62
Migrate to ocamlmerlin-lsp #269
base: master
Are you sure you want to change the base?
Conversation
Could you write a summary of what's removed and what's added here? |
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.
Great! I've left some comments inline.
.vscode/settings.json
Outdated
@@ -1,5 +1,5 @@ | |||
{ | |||
"editor.formatOnSave": true, | |||
// "editor.formatOnSave": true, |
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.
Unrelated change?
package.json
Outdated
"enum": ["merlin", "bsb"] | ||
"enum": [ | ||
"merlin", | ||
"bsb" |
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 keep support for bsb
diagnostics here?
src/formatters/reason.ts
Outdated
{ | ||
provideDocumentFormattingEdits(_document: vscode.TextDocument): vscode.TextEdit[] { | ||
const formatterPath = configuration.get<string | undefined>("path.refmt"); | ||
const formatter = formatterPath ? path.resolve(rootPath, formatterPath) : "/usr/local/bin/refmt"; |
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.
Should this be just refmt
so it is being resolved from PATH
instead of hard coding to /usr/local/bin/refmt
?
src/formatters/reason.ts
Outdated
fs.writeFileSync(tempFileName, textEditor.document.getText(), "utf8"); | ||
const formattedText = execSync(`${formatter} ${tempFileName}`).toString(); | ||
const textRange = getFullTextRange(textEditor); | ||
fs.unlinkSync(tempFileName); |
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.
If we use temporary file we'd want to remove it incase refmt
produces an error. But we probably can just pipe input on stdin instead?
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.
I tried it, but it doesn't work with large files
src/formatters/reason.ts
Outdated
if (textEditor) { | ||
const tempFileName = `/tmp/vscode-refmt-${uuidv4()}.re`; | ||
fs.writeFileSync(tempFileName, textEditor.document.getText(), "utf8"); | ||
const formattedText = execSync(`${formatter} ${tempFileName}`).toString(); |
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.
I think this lacks error handling — what happens if we try to reformat invalid code? This will throw?
@@ -0,0 +1,37 @@ | |||
import { execSync } from "child_process"; |
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.
Same comments I left for reason formatter are applicable to this too, I think.
src/client/index.ts
Outdated
return serverOptions; | ||
} | ||
|
||
export async function launchMerlinLsp(context: vscode.ExtensionContext, useEsy: boolean): Promise<void> { |
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.
Let change useEsy
arg to be options: {useEsy: bool}
instead, this will make things more clear on call sites.
@andreypopp, I edited the description to mention removed features and addressed your comments I guess I also need to provide a guide on how to build |
src/formatters/ocaml.ts
Outdated
const textEditor = vscode.window.activeTextEditor; | ||
|
||
if (textEditor) { | ||
const tempFileName = `/tmp/vscode-reasonml-${uuidv4()}.ml`; |
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 should be using os.tmpdir()
instead of /tmp
- otherwise it won't work correctly on Windows.
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.
I didn't think about windows at all. Will try to setup vm and test it there this week
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.
Thanks @rusty-key !
from this list:
only "case splitting" is still unsupported by merlin-lsp, others were implemented in ocamlmerlin-lsp |
"reason.diagnostics.tools": { | ||
"type": "array", | ||
"items": { | ||
"enum": ["merlin", "bsb"] |
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.
@rusty-key @andreypopp One of the main advantages of this bsb integration was that bsb has full project visibility. So if one file changes and that change breaks other files, bsb is able to show those errors in the Diagnostics panel, even if the file is not opened. One has just to click on them to open the broken file, which is useful for large refactors.
Is something like that possible with merlin? I always believed that merlin only has a "local view" of the world. 🤔
Another question: what's the best way to keep compatibility with Ideally, this extension could be used to run both BuckleScript and native projects, but I wonder what's the best way to use merlin with BS projects, considering it doesn't play well with esy yet? cc @andreypopp |
@jchavarri I've been managing native dependencies with esy in bs projects so far — |
I included precompiled (with Next steps are: |
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.
Thanks for this @rusty-key !!
src/client/index.ts
Outdated
if (options.useEsy) { | ||
run = { | ||
args: ["exec-command", "--include-current-env", merlinLsp], | ||
command: process.platform === "win32" ? "esy.cmd" : "esy", |
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.
The way this is implemented has some unexpected behavior. If I'm understanding correctly, if user sets in settings.json
:
{
"reason.path.ocamlmerlin-lsp": "/some/folder/ocamlmerlin-lsp"
}
then the command will be
esy /some/folder/ocamlmerlin-lsp
but I would expect it to be just
/some/folder/ocamlmerlin-lsp
If the path is set manually, then it should be used "as is", imo.
"default": "./node_modules/bs-platform/lib/bsb.exe", | ||
"description": "The path to the `bsb` binary." | ||
}, | ||
"reason.path.ocamlfind": { |
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.
@jordwalke Heads up: this will remove the APIs for introspecting environments that were added in https://github.com/freebroccolo/ocaml-language-server/pull/68.
package.json
Outdated
"type": "string", | ||
"default": "ocamlfind", | ||
"description": "The path to the `ocamlfind` binary." | ||
}, | ||
"reason.path.esy": { |
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.
@rusty-key I think this can be removed too, it was used for the env introspection (like ocamlfind
, env
etc)
src/client/index.ts
Outdated
env: { | ||
...process.env, | ||
MERLIN_LOG: "-", | ||
OCAMLFIND_CONF: "/dev/null", |
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.
Does this have any implications? Why does merlin fail if this is not set? cc @andreypopp
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.
afaiu, merlin relies on ocamlfind
by default and when it is not there, it fails. This flag can be removed as soon as findless
branch will be merged and released:
https://github.com/ocaml/merlin/tree/findless
One thing I'm noticing when testing this branch is that when opening
I guess it has to do with the version of the Reason parser that is included with |
Hm. Can't repro with |
That's probably because I included |
src/formatters/utils.ts
Outdated
|
||
if (!formatter) { | ||
vscode.window.showInformationMessage( | ||
`${formatterPath} is not available. Please specify "vscode-reasonml.path.${formatterName}"`, |
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.
Please specify "vscode-reasonml.path.${formatterName}"
This message is not correct. The setting would be reason.path.refmt
.
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.
Unrelated, but I can't get refmt to work even when using the right config.
78d74be
to
bf91e25
Compare
So, I talked to @jchavarri and we agreed that the best workflow would be one with But I still really want to provide a seamless experience for BS users who don't want to deal with
If we can't detect either, we just stop and ask user to provide of these configurations, because we have no idea what to do. Next, we can provide a creation or population of esy.json and probably run esy to install dependencies. Also, I wonder, if we can hide all of this into extension internals and detect compiler version based on project configuration. @andreypopp @jchavarri @jordwalke what do you think? |
add local opam switch support
Can we perhaps make the scope of this PR more limited and merge it? Like, if there's no ocamlmerlin-lsp in path, just add an error and say that it's not in the path? It would be a great improvement itself and any follow ups would be just icing on the cake! |
@wokalski, makes sense to me. I'll prepare changes over the week |
@wokalski, it was quite a long week :) I dumbed down the extension. Now it requires I'll return to |
Is this abandoned? People were recommending |
@jfrolich take a look at |
Original PR is here: #264
Native LSP implementation was merged recently into merlin repository. This PR switches extension to use it instead of OLS. This goes with some features removed (temporarily, I hope):
— find occurances;
— symbol rename;
— case splitting;
— code lens.
Also, it adds support for
ocamlformat
/refmt
, because it was handled by OLS.What do you think? What else should be done here?