reasonml-editor / vscode-reasonml Goto Github PK
View Code? Open in Web Editor NEWOCaml & Reason support for Visual Studio Code
License: Apache License 2.0
OCaml & Reason support for Visual Studio Code
License: Apache License 2.0
Hi @freebroccolo. vscode-reasonml continues to be an excellent plugin.
I noticed one issue. When hitting enter after this semicolon, a pattern matching bar is inserted.
This really needs some work in the Reason support both in how the highlighting for signatures is selected (in order to deal with ambiguity) and in what gets shown in the hover.
I've discovered several problems with it:
I think there's more, but they've slipped my mind. I'll update this when I come across them.
I'm playing around with https://github.com/bsansouci/reasonglexampleproject on the branch bsb-support
. When I boot up VSCode, I see the [loading]
status forever. No completion or refmt, etc.
I can't find a good way to debug and see what's going on under the hood. Any tips on how to find more info?
Details here. It's more difficult in our case though because we don't have the enclosing parentheses.
I think that in order to implement this we will need to do some traversals of the syntax tree so that we can find the head of the application. There are a few ways one could do this using a combination of enclosing
, shape
, and type enclosing
commands but it might just be easier and faster to do the traversal without merlin. Basically, given a position, search backward until the scope boundary is found and record the distance in nodes from the origin; this should be enough to reconstruct the rest.
This would provide some visual indication as to whether or not the language server can provide advanced features for the current buffer. We also could make the indicator into a clickable widget.
Currently completion for object methods only seems to work once you start typing a method name after #
. This isn't as useful as completion for records because you need to know at least the first character of the method name.
This seems to be an issue with merlin although I'm not sure why. However, we should be able to work around it by detecting when #
is typed and first reconstructing the initial list of methods from the inferred type.
This would allow the user to easily tab through the patterns and cases added to the buffer.
Since we're now watching files in order to maintain the symbol index we might as well exploit that for other scenarios too. One easy thing we could do is avoid recomputing the codelens items when switching editors unless the underlying document has been modified.
Some features potentially make a lot of calls to merlin in rapid succession and/or take a long time (relatively speaking) to complete. Examples of this are the codelens feature and diagnostic refreshing for the entire workspace (currently disabled). Find all references for workspace is another one since it will need to do searching and reverse lookups.
In order to keep the more interactive features like hover, outline, and code splitting responsive while these other features are executing, we should really be using a priority queue instead of just running everything in a straight sequence.
Could you show the errors returned by merlin? Also errors when merlin is not found.
Right now we just use the signature reported from merlin at the point of definition. Most of the time this is okay but it can lead to less than optimal results for fancier types involving lots of polymorphic variants or first-class modules.
Probably the right way to do this is to gather and store the signatures from annotations and interfaces files in the symbol index so we can retrieve them quickly. Then we would modify the codelens feature to first check the index and only query merlin if no results are found.
Should probably do it before the next release. This will make it easier to synchronize the grammars with nuclide and elsewhere.
Merlin is being triggered on inmemory://
editors such as diff views, producing a list of non-existing problems in the problems pane. These should be filtered out.
This highlights fine:
{x: (fun x => 22), y: 33};
And this loses the blue field-name highlighting on y
:
{x: fun x => 22, y: 33};
The latter is how refmt
automatically normalizes this example.
Hello @freebroccolo ,
First off, thanks for this beautiful plugin! ๐
This issue is regarding the can't locate ocamlmerlin
warnings. Actually I have merlin installed as well as the emacs reason-mode
which works fine. But the warning keeps popping up with the vscode-reasonml
extension.
It might be a trivial question but I thought that it'd be better to have this documented.
Could you please help me out?
For example, after type let str = "้ณ"
and save, the character ้ณ changed into ๏ฟฝ\152๏ฟฝ. I use vim to edit the same file and everything works fine.
Is it the problem with this plugin or merlin?
The current default behavior is to show subtle highlighting of identifiers on hover. However, this doesn't really mesh well with the position
info which is supposed to indicate whether an expression is in a tail (call) position.
What happens is that when you hover over the head term of an application, it will report position: normal
, which is fine, but a little bit surprising. You only see the position: tail
if you hover slightly in front of the head term but now you don't see anything highlighted in the buffer because there is no identifier under the cursor. What should happen is the entire application should be highlighted.
tldr: the highlighting extents on hover should be calculated by merlin from the shape of the expression at the cursor position rather than being calculated by the editor based on identifiers.
Sometimes I would like to disable the code lens. I think we could have a configuration option and a command to turn it on and off either locally or globally.
This is a feature request
In merlin mode for emacs, there is a function to jump to enclosing fun, let, module or match, which is very convenient. I would love to have it in vscode too.
In addition, it could be nice to display somewhere those information (in which enclosing fun, let, module, match, the cursor currently is), maybe in the status bar.
Not present in the old protocol doc, but the command is available. I think it is something like ["jump", "fun let module match", "at", POSITION]
(defun merlin/jump (&optional target)
"Jump to the TARGET"
(let ((result (merlin/send-command
(list 'jump (if (equal target "") "fun let module match" target)
'at (merlin/unmake-point (point))))))
(unless result
(error "Not found. (Check *Messages* for potential errors)"))
(unless (listp result)
(error result))
result))
C-c C-j runs the command merlin-jump, which is an interactive Lisp
function in `merlin.el'.
It is bound to C-c C-j.
(merlin-jump &optional TARGET)
Jump to enclosing fun, let, module or match.
Any combination of the above may be entered, separated by spaces, ex.:
fun let or module or module fun match
Empty string defaults to jumping to all these.
Completion should not trigger when typing ..
for types or ...
for patterns.
When merlin completion is triggered, it will return possible values at the point in a given order. This order matters because merlin will try to give the values that have the expected type first.
I don't know if the order is changed by vscode, the language server or this extension, but it would be nice to keep the values in the order given by merlin.
(I never know if I should report the issues on this repo or in the ocaml-language-server one, let me know if it's not at the good place)
This is sort of an open-ended question, but I am curious if you might summarize (if you haven't already somewhere) some of the key points to keep in mind for creating a VS Code extension like this.
If I were to create an extension like this for another language, what would be a good starting point? What would be some best practices to follow, or pitfalls to avoid?
Thanks for any direction you might suggest and for your work on this extension!
An issue with the current codelens behavior is that all of the codelenses for items in a local module are refreshed together, which means that if one of the items has a syntax error, the others collapse until it is fixed. If you have a lot of short single line definitions together and are doing a lot of editing, this effect can be slightly annoying.
We can't actually refresh the items individually due to the way merlin works here (afaik), so what we need to do instead is have some sort of caching of the items. Then, if there is a syntax error from editing, we just continue to show the last good codelens data for the other items until all of the diagnostics are resolved.
However, getting this to work is a little bit trickier than it first seems. I tried doing it in a naive way earlier and it sort of worked but the behavior wasn't consistent. I think the issue was that when codelenses are resolved (in the second phase), the change isn't necessarily propagated back to something holding on to the original CodeLens
. If this is indeed the case, we can work around it by building a map and associating a unique id with each codelens and manually doing the update. It's possible that some other event was interfering with the caching though. Need to do more testing.
Another alternative which would be easier but less useful would be to simply disable codelens refreshing for whatever the current item is with respect to the cursor position (followed back up to the associated top-level node). But in order to make this work I think we'd have to listen for some other events too so it may end up being messier in the end.
One particularly annoying example is when typing semicolon followed (slowly) by enter, it will insert some random identifier. This is of course done on the end of most lines of code, so it happens quite often.
I am very happy with this extension and I would like to support your work. I could be nice to have a bountysource like merlin or another way to contribute. I would be happy to give some money to support you.
Merlin doesn't provide very good Reason syntax error information; in particular the location of the error is often way off. The positional information from refmt is way better, so I think it would make sense to implement a linter which sends the code to refmt upon change, and displays any errors. You can see how sublime-reason uses refmt as a linter here: https://github.com/chenglou/sublime-reason/blob/master/Reason.py#L77-L95
If what I'm saying sounds good, I'm happy to have a go at implementing it. I've already put up a similar PR for atom-reason-refmt
Example of unhelpful syntax error info (the error is on line 6 but the Invalid token
error points to line 8):
It seems that the tail call
information given by merlin is not displayed (or I missed it)
Simple test case:
let rec test () =
if 1 + 2 = 3 then
test ()
else
(<cursor>)
The displayed type is unit
and I don't see tail call
anywhere.
I searched a little bit and found those related commits and issues:
I tried to play with syntaxes/ocaml-hover-{type,signature}.json
to make them look like the syntaxes/reason-hover-{type,signature}.json
files but without success.
Often problems picked up by merlin in one file is fixed by altering a different file, but this isn't picked up so the problems go stale. This is particularly annoying if you delete a file that had problems associated with it. Then you're pretty much screwed and have to restart vscode to fix it.
And of course the opposite is true as well. Changes in one file might cause errors in other files that merlin doesn't pick up.
But in general, thanks for awesome work!
I believe there is support of code formatting for reason using refmt. I would like to have the support of ocp-indent for the OCaml code. With the possibility to format all the document, only my selection or only one line.
I wonder if this should be done in this extension or if it's better to have a new extension for ocp-indent.
Since version 2.1, merlin has this "smart" completion feature:
- "smart" (a.k.a "do what I mean") completion:
`L.m` will expand to `List.map ; List.m... ; ListLabels.map ; ...` if
`L` doesn't exist.
I don't know if this could be added in this extension of in the ocaml-language-server. But it's a nice feature to have.
Great plugin!!
I assume reason.path.rtop is to hook VSCode / ReasonML to REPL functionality, and set it to my rtop, but cannot figure out how to use it. Could not find suitable forum to ask this question ...
I think it would be nice to provide formatOnSave
powered by refmt
.
Made a local extension which does the job. If you want, I can submit a PR which integrates this
into vscode-reasonml
.
events.js:160
throw er; // Unhandled 'error' event
^
Error: write EPIPE
at exports._errnoException (util.js:1022:11)
at WriteWrap.afterWrite [as oncomplete] (net.js:804:14)
[Error - 10:14:56 AM] Connection to server got closed. Server will not be restarted.
I installed reason/merlin/merlin-extend via opam, it is in PATH
I'm not entirely sure this is an issue with vscode-reason, but I'm also not sure where else to look. I am starting a project with the reason-react-example
code found here. One of the files looks like this:
module PageReason = {
include ReactRe.Component.JsProps;
type props = {message: string, extraGreeting: option string};
let name = "PageReason";
let render {props} => {
let greeting =
switch props.extraGreeting {
| None => "How are you?"
| Some g => g
};
<div> <MyBannerRe show=true message=(props.message ^ " " ^ greeting) /> </div>
};
/* extraGreeting is optional, which means the JS side might pass in a null or undefined */
type jsProps = Js.t {. message : string, extraGreeting : Js.null_undefined string};
let jsPropsToReasonProps =
Some (
fun jsProps => {
message: jsProps##message,
extraGreeting: Js.Null_undefined.to_opt jsProps##extraGreeting
}
);
};
include ReactRe.CreateComponent PageReason;
let createElement ::message ::extraGreeting=? => wrapProps {message, extraGreeting};
I am trying to understand where the Js
variable is coming from, what it does etc. but jump to definition is not working on it, instead it says no definition found. This is also true of the MyBannerRe
component, which is in a sibling file.
Any help would be appreciated. Thank you!!
Remaining tasks:
class
inherit
for
while
We should be able to use the merlin case splitting functionality to automatically fill in a standard set of patterns for fun
and switch
as part of the indent action.
So far the extension works like magic ๐
I do have two issues,
ReasonML
code from the editor?A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.