Skip to content

Commit 8514193

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 bbe1622 commit 8514193

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
@@ -337,22 +337,48 @@
337337
"jsx": {
338338
"patterns": [
339339
{
340-
"match": "<>|</>|/>"
340+
"match": "<>|</>|/>",
341+
"name": "punctuation.definition.tag"
341342
},
342343
{
343344
"match": "</([A-Z_][0-9a-zA-Z_]*)",
344345
"captures": {
346+
"0": {
347+
"name": "punctuation.definition.tag"
348+
},
345349
"1": {
346350
"name": "entity.name.namespace"
347351
}
348352
}
349353
},
350354
{
351-
"match": "</([a-z_][0-9a-zA-Z_]*)"
355+
"match": "</([a-z_][0-9a-zA-Z_]*)",
356+
"captures": {
357+
"0": {
358+
"name": "punctuation.definition.tag"
359+
},
360+
"1": {
361+
"name": "variable"
362+
}
363+
}
364+
},
365+
{
366+
"match": "<([a-z_][0-9a-zA-Z_]*)",
367+
"captures": {
368+
"0": {
369+
"name": "punctuation.definition.tag"
370+
},
371+
"1": {
372+
"name": "variable"
373+
}
374+
}
352375
},
353376
{
354377
"match": "<([A-Z_][0-9a-zA-Z_]*)",
355378
"captures": {
379+
"0": {
380+
"name": "punctuation.definition.tag"
381+
},
356382
"1": {
357383
"name": "entity.name.namespace"
358384
}

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)