-
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
Universal dot completion #1054
Universal dot completion #1054
Conversation
"label": "->SomeModule.getName", | ||
"kind": 12, | ||
"tags": [], | ||
"detail": "t => string", | ||
"documentation": null, | ||
"sortText": "getName", | ||
"insertText": "->SomeModule.getName" | ||
}, { | ||
"label": "name", | ||
"kind": 5, | ||
"tags": [], | ||
"detail": "string", | ||
"documentation": {"kind": "markdown", "value": "```rescript\nname: string\n```\n\n```rescript\ntype t = {name: string}\n```"} | ||
}] |
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 is the relevant test output.
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.
Any chances this affects library design? Core?
Path n | ||
Path SomeModule. | ||
[{ | ||
"label": "->SomeModule.getName", |
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.
curious about the function coming before the field
also, any thoughts about making .
a valid source language construct?
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.
Could you expand a bit?
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.
1 If I write x.
I see x->getName()
before x.field
, which can be surprising to people working with records. Just wondering.
2 Could x.getName()
be actually part of the language, or will it always need to be expressed as x->getName
? Autocompletion is right now suggestive of something that does not exist in the language. Not necessarily a bad thing, just thinking aloud about possible pros and cons 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.
- Ahh right! That's a good point. It's currently sorted on the field name and function name. We could sort it whatever way we think works best. I'd say either this (sort it together with the regular fields) or put it at the bottom. I'd favor the current way, I think.
- Oh, that's.... a very interesting idea! That would solve quite a few of our issues. Let's explore that!
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.
It seems that is about what called "uniform function call syntax"
And there was a similar discussion in ReasonML reasonml/reason#1638 early day
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.
Thank you for the context. Will read through.
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 wonder if we could figure out a good way to do that, pointing out the module to use with the call (someRecord.SomeModule.someFn()
), but with a small enough twist that it's still more convenient than pipe, but not ambigious wrt the current behavior of SomeModule
there being a hint.
Anyway, just completing the actual pipe, but via dot, is a good start for DX imo.
I don't think so. It should mostly just simplify things, and I also think with this we could get rid of some the special casing for pipe completions we have, and just add the annotation to types shipped with the compiler. |
Ok, so this PR explicitly handles (resolvable) record types only, because this was originally intended to cater to a potential use case in https://github.com/rescript-lang/experimental-rescript-webapi. But, this could easily be useful in more general cases. Examples:
The latter part opens up some pretty good optimizations for people used to JS/TS: "some string".
// ^com JS/TS users would expect the above to complete for Expanding dot completion to also complete for relevant pipe functions here would make that much more discoverable. I would also think it would mean there's a good chance people will just learn the convention of "main type, pipe functions from module of that main type" automatically because they'll see what their expected dot completion is resolved to. This would be a massive win because that means that the tooling could help teach one of the larger differences between how things are done in ReScript vs JS. |
// ^com | ||
// ^dv- | ||
|
||
@mainTypeForModule(SomeOtherModule) |
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.
Would this also work when SomeOtherModule
is another file?
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.
Yes, it's effectively just a path to a module, so it'll take that exact module path and try to complete it from whatever point you're completing. So it's simulating doing whateverToComplete-><pathFromMainTypeForModuleHere>.<com>
.
type typeOutsideModule = {nname: string} | ||
|
||
module SomeOtherModule = { | ||
type t = typeOutsideModule |
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.
Is this alias as t
a hard requirement to make this work?
Being newish to ReScript type t
is a little strange and it feels a bit like an artificial limitation right now.
…cord is type t of module
* Add Rxjs completion test * Add Rxjs binding example * Extend Rxjs test with fully qualified access * Add@editor.completeFrom and incomplete test output * Add passing test for property completion * Test still works when types are not named t. * Add test for @editor.completeFrom
d3420b3
to
b5053bc
Compare
Broadens the scope for dot completions to (in addition to record fields) cover:
@editor.completeFrom
on the type being completedThe editor will automatically handle inserting what you complete for properly into the code, so even if you trigger a completion with a dot, that dot will be removed if you select a completion that's not an actual record field.
Example:
This should complete for both
name
(record field),getName
(function from parent module that takes this record as the first argument) anddoStuff
(pipable function from module defined via@editor.completeFrom
).Experimental
@editor.completeFrom
annotationThis PR also introduces an experimental
@editor.completeFrom
annotation, that lets you provide more modules the tooling can draw additional completions from. This is useful because there are situations where you need to draw completions from another module than what the type belongs to, or when you can't put the type inside of its own module (and get completions via that). Examples include recursive type chains, where the type definition might need to live outside of the module, and similar.Annotating with
@editor.completeFrom
will make the editor tooling complete for pipes from the provided module too. Example:This will complete for:
nname
(record field)getNName
(pipe from module)getNName2
(pipe from module)The annotation has no other effect than providing a hint for the editor tooling.