Skip to content

Commit 3abef20

Browse files
committed
Semantic highlighting: show brackets in jsx like TypeScript does.
This is done in two places: The textmate grammar handles the cases that can be figured out locally: - "<" in "<div ..." - "</" - "/>" - "<>" - "</>" Semantic highlighting handles the cases that cannot be figured out locally: - ">" in "<div __props__>" - ">" in "</div>" These cases can't be figures out locally as on the lhs of ">" there could be pretty much anything.
1 parent 779c890 commit 3abef20

File tree

4 files changed

+66
-15
lines changed

4 files changed

+66
-15
lines changed

analysis/src/SemanticTokens.ml

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ let emitFromLoc ~loc ~type_ emitter =
9999
emitter |> emitFromPos posStart posEnd ~type_
100100

101101
let emitLongident ?(backwards = false) ?(jsx = false)
102-
?(lowerCaseToken = if jsx then Token.JsxTag else Variable)
103-
?(upperCaseToken = Token.Namespace) ~pos ~lid ~debug emitter =
102+
?(lowerCaseToken = Token.Variable) ?(upperCaseToken = Token.Namespace) ~pos
103+
~lid ~debug emitter =
104104
let rec flatten acc lid =
105105
match lid with
106106
| Longident.Lident txt -> txt :: acc
@@ -148,6 +148,10 @@ let emitJsxOpen ~lid ~debug ~loc emitter =
148148
let emitJsxClose ~lid ~debug ~pos emitter =
149149
emitter |> emitLongident ~backwards:true ~pos ~lid ~jsx:true ~debug
150150

151+
let emitJsxTag ~debug ~pos emitter =
152+
if debug then Printf.printf "JsxTag >: %s\n" (posToString pos);
153+
emitter |> emitFromPos pos (fst pos, snd pos + 1) ~type_:Token.JsxTag
154+
151155
let emitType ~id ~debug ~loc emitter =
152156
if debug then Printf.printf "Type: %s %s\n" id (locToString loc);
153157
emitter |> emitFromLoc ~loc ~type_:Token.Type
@@ -227,10 +231,25 @@ let parser ~debug ~emitter ~path =
227231
let lineEnd, colEnd = Utils.tupleOfLexing pexp_loc.loc_end in
228232
let length = if lineStart = lineEnd then colEnd - colStart else 0 in
229233
let lineEndWhole, colEndWhole = Utils.tupleOfLexing e.pexp_loc.loc_end in
230-
if length > 0 && colEndWhole > length then
234+
if length > 0 && colEndWhole > length then (
231235
emitter
232236
|> emitJsxClose ~debug ~lid:lident.txt
233-
~pos:(lineEndWhole, colEndWhole - 1));
237+
~pos:(lineEndWhole, colEndWhole - 1);
238+
239+
let rec emitGreatherthanAfterProps args =
240+
match args with
241+
| (Asttypes.Labelled "children", {Parsetree.pexp_loc = {loc_start}})
242+
:: _ ->
243+
emitter |> emitJsxTag ~debug ~pos:(Utils.tupleOfLexing loc_start)
244+
| _ :: args -> emitGreatherthanAfterProps args
245+
| [] -> ()
246+
in
247+
emitGreatherthanAfterProps args (* <foo ...props > <-- *);
248+
emitter (* <foo> ... </foo> <-- *)
249+
|> emitJsxTag ~debug
250+
~pos:
251+
(let pos = Utils.tupleOfLexing e.pexp_loc.loc_end in
252+
(fst pos, snd pos - 1))));
234253
(* only process again arguments, not the jsx label *)
235254
let _ = args |> List.map (fun (_lbl, arg) -> mapper.expr mapper arg) in
236255
e

analysis/tests/src/expected/Parser.res.txt

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,18 @@ Variable: _c (4,4)->(4,6)
88
Ldot: M (6,11) Namespace
99
Lident: C (6,13) Namespace
1010
Variable: _mc (6,4)->(6,7)
11-
Lident: div (8,10) JsxTag
11+
Lident: div (8,10) Variable
1212
Variable: _d (8,4)->(8,6)
13-
Lident: div (11,3) JsxTag
14-
Lident: div (16,4) JsxTag
13+
Lident: div (11,3) Variable
14+
Lident: div (16,4) Variable
15+
JsxTag >: (11,6)
16+
JsxTag >: (16,7)
1517
Ldot: React (12,5) Namespace
1618
Lident: string (12,11) Variable
17-
Lident: div (13,5) JsxTag
18-
Lident: div (13,34) JsxTag
19+
Lident: div (13,5) Variable
20+
Lident: div (13,34) Variable
21+
JsxTag >: (13,8)
22+
JsxTag >: (13,37)
1923
Ldot: React (13,11) Namespace
2024
Lident: string (13,17) Variable
2125
Ldot: React (14,5) Namespace
@@ -75,7 +79,9 @@ Variable: world (69,24)->(69,30)
7579
Variable: x (69,21)->(69,22)
7680
Variable: add (69,4)->(69,7)
7781
Lident: add (71,8) Variable
78-
Lident: div (73,9) JsxTag
79-
Lident: div (73,36) JsxTag
80-
Lident: div (73,27) JsxTag
82+
Lident: div (73,9) Variable
83+
Lident: div (73,36) Variable
84+
JsxTag >: (73,24)
85+
JsxTag >: (73,39)
86+
Lident: div (73,27) Variable
8187

grammars/rescript.tmLanguage.json

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,22 +344,48 @@
344344
"jsx": {
345345
"patterns": [
346346
{
347-
"match": "<>|</>|/>"
347+
"match": "<>|</>|/>",
348+
"name": "punctuation.definition.tag"
348349
},
349350
{
350351
"match": "</([A-Z_][0-9a-zA-Z_]*)",
351352
"captures": {
353+
"0": {
354+
"name": "punctuation.definition.tag"
355+
},
352356
"1": {
353357
"name": "entity.name.namespace"
354358
}
355359
}
356360
},
357361
{
358-
"match": "</([a-z_][0-9a-zA-Z_]*)"
362+
"match": "</([a-z_][0-9a-zA-Z_]*)",
363+
"captures": {
364+
"0": {
365+
"name": "punctuation.definition.tag"
366+
},
367+
"1": {
368+
"name": "variable"
369+
}
370+
}
371+
},
372+
{
373+
"match": "<([a-z_][0-9a-zA-Z_]*)",
374+
"captures": {
375+
"0": {
376+
"name": "punctuation.definition.tag"
377+
},
378+
"1": {
379+
"name": "variable"
380+
}
381+
}
359382
},
360383
{
361384
"match": "<([A-Z_][0-9a-zA-Z_]*)",
362385
"captures": {
386+
"0": {
387+
"name": "punctuation.definition.tag"
388+
},
363389
"1": {
364390
"name": "entity.name.namespace"
365391
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"semanticTokenScopes": [
3232
{
3333
"scopes": {
34-
"jsx-tag": ["entity.name.tag"]
34+
"jsx-tag": ["punctuation.definition.tag"]
3535
}
3636
}
3737
],

0 commit comments

Comments
 (0)