pangloss / vim-javascript

Vastly improved Javascript indentation and syntax support in Vim.
http://www.vim.org/scripts/script.php?script_id=4452
3.79k stars 357 forks source link

object destructing #1092

Open ycmjason opened 6 years ago

ycmjason commented 6 years ago

The color are not quite right for default values in object destructing. Below should be a reproducible code.

({
  a = 3,
  b = Math.min(a, 100) / 3,
}) => {
  /* ... */
}
amadeus commented 6 years ago

Yeah this is a known issue and I am not entirely sure it's possible to fix with Vim's built in regex syntax system.

The TL;DR is that we can only really detect them as arguments if the opening and closing paren are on the same line.

ycmjason commented 6 years ago

This is so sad, no regex guru is solving this?

jigfox commented 6 years ago

It doesn't work with one line either:

function someDefault() {}
export const a = ({first: f, second: s = someDefault()}) => {
  return f + s;
}
ycmjason commented 6 years ago

@jigfox i know this is really sad. do you wanna look into the plugin and fix this please. i want proper syntax highlighting.. 😢

jigfox commented 6 years ago

sorry, but I don't know how, I have never done any syntax highlighting for vim, I just stumbled over the problem myself, and then I found this issue

ycmjason commented 6 years ago

😭

amadeus commented 6 years ago

@jigfox your example breaks because there are parens in it, not because it's on one line.

export const a = ({first: f, second: s = 2}) => {
  return f + s;
}

This above example will work fine.

Thing is, there might be a super complex regex that can do this, but it would most likely make our syntax highlighting very slow (if someone can figure it out, I am would be more than willing to test it, but I doubt it's possible and performant).

Just for some context on why it is expensive/hard:

an opening ( can mean a couple different things. It can mean an expression or it can mean an arrow function arguments. What makes it an arrow function argument, is that AFTER its closing paren, there has to be => - this is something tokenizers do a great job of, but not a regex parser (known as a look ahead).

On it's own it's not that complex, but when you add the possibility of destructuring, it gets insanely complex.

({example: [x = 2 + 2, {another = ({wow = (2 + x) / 10}) => [wow, another]}]}) => {};

This is a valid destructuring statement, and knowing how to find the actual beginning and end of each matching parenthesis is just a flat out nightmare for a regex. It's best done with a tokenizer.

I actually kinda wish that Vim had a sort of async api that you could pipe a file through a tokenizer and then have it return syntax highlighting information - so we could initially use our regex stuff, then when the tokenizer parses it properly, update it to the correct syntax highlighting groups (this is often what IDEs do)

bounceme commented 6 years ago

I see, the inner () is the problem, il look into it

bounceme commented 6 years ago

could it just skip jsExpression? i think skipping nested parens is possible with vim syntax engine, but it needs one additional sytax match for each level, and it doesn't allow recursion, so it is really ugly.

bounceme commented 6 years ago

anyways, the syntax stuff is really hard, have to keep in mind priority and stuff

amadeus commented 6 years ago

@bounceme I don't think we can use the syntax region feature either, because it only requires matching on the start argument and doesn't require the ending regex to match. There's no way to differentiate or prioritize it over the jsParen group. Basically we'd have to create an insane regex, then basically have it contain a ton of other shit in order to work, and we'd get none of the great region features that we normally get for free.

~I work around this by forcing the current arrow argument region to be oneline. This enables the @end regex to match in order to continue.~ I've actually since refactored it and don't do this anymore, but I forget why.

I actually made a request on the Vim mailing list - to add a feature to region like requireend to require the end argument to match in order for the region to match, but Braam pushed back saying it went against what regions are intended for and could affect performance.

ycmjason commented 5 years ago

any update on this?

I am slowly moving to VSCode now because vim's syntax highlighting support seems incomplete. Thank you @amadeus for spending so much time on this tho!

The Vim experience on VSCode is not perfect 😢

amadeus commented 5 years ago

Nope, there's no update. Until we can use a tokenizer to do syntax highlighting, i don't think this issue will ever get fixed.

yuezk commented 5 years ago

The reason is that the jsArrowFuncArgs group doesn't support multiline parameters,

I tried to define the jsArrowFuncArgs using region, it will fix this issue, but it will break the jsParsen group. E.g., parens in (a + b) / 10 will be matched as jsArrowFuncArgs incorrectly.

The root cause for this issue is that the parens expression and the arrow function arguments are ambiguous. For example, (a, b, c) is a parens expression, while (a, b, c) => is a arrow function arguments. We can not decide what it is until we see the => sign. And it's not possible to distinguish them in the Vim syntax file.

Another proposed solution is that we shall not distinct the arrow function arguments parens from the normal parens. We treat the former as the normal parens, and the syntax should work. Although the arrow function arguments may not be highlighted precisely, it won't break the following syntax highlighting.

datfinesoul commented 2 years ago

Has anything ever come up in the past 3 years that now makes this possible?

amadeus commented 2 years ago

Treesitter support in Neovim can do it, but then you wouldn’t be using this plugin at all