microsoft / TypeScript-TmLanguage

TextMate grammar files for TypeScript for VS Code, Sublime Text, and Atom.
MIT License
398 stars 125 forks source link

Javascript highlighting fails when less than symbol ("<") is first char and followed by greater than (">") #884

Open vike2000 opened 2 years ago

vike2000 commented 2 years ago

TS and JS Grammar Extension version: clicking previous link (in chrome 91.0.4472.114 on macos 10.13.6) gives 404 but searching vscode 1.59.1 extensions for @builtin typescript shows vscode.typescript-language-features 1.0.0 and vscode.typescript 1.0.0. Installing ms-vscode.vscode-typescript-next 4.5.20210902, found in this repo's readme, made no difference.

Code

vscode language mode: JavaScript

const x = 1;
0
< x
&& 1 > 0 // incorrect syntax highlight color coding

Screen Shot 2021-09-03 at 17 54 05

The issue seems to be that < x … > is interpreted as some type specification (like in array<int>)? Compare with following where the last x is replaced with 1.

const x = 1;
0
< 1
&& 1 > 0 // correct syntax highlight color coding

Screen Shot 2021-09-03 at 17 55 02


I found #752 but decided to open a new issue.

orta commented 2 years ago

Confirmed, it's only present in .js files - you don't get the same in .ts files. Open to well-scoped PRs which fix it 👍🏻

NotWearingPants commented 2 years ago

I found #752 but decided to open a new issue.

This was also in #718

The issue seems to be that < x … > is interpreted as some type specification (like in array)?

It's not interpreted as a type specification, but rather as a JSX tag, e.g. return <div></div>. Since 1 is not a valid JSX tag name it works fine. But replace x with x1 or x.y or x-y or x_y and it will still break.

The highlighting really breaks, even more so after the tag is closed with >:

image

Confirmed, it's only present in .js files - you don't get the same in .ts files.

This happens in .js/.jsx/.tsx but not in .ts. The .js syntax is equivalent to .jsx because reasons (the VSCode team decided that JSX is common enough to have it always on), that's why this problem can happen there.

The core issue is that it should recognize it's in the middle of an expression and not try to match a JSX tag there, but this is only because ASI won't add a semicolon when the line starts with an angle bracket. I'm not familiar with TM but I'm not sure this can be fixed.

For example, when the previous line(s) is one of these, a < should be matched as a less-than-sign (keyword.operator.relational.js):

let x = 1
let x = {}
let x =
{}

But if the previous line(s) is one of these, a < should be matched as a JSX tag (punctuation.definition.tag.begin.js):

let x = 1;
let x =
let x = 1 +
let x = (
;
{}

The {} are a bit of an edge case in JS so I don't think it's a big deal if it's a limitation, but can the rest of this be done? @orta