diff --git a/CHANGELOG.md b/CHANGELOG.md index ca190d92d3..a16bbd0945 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ #### :bug: Bug fix +- Fix semantic highlighting for array spreads, array access and dict literals. https://github.com/rescript-lang/rescript/pull/7789 - Preserve `@as(...)` decorator on record fields when creating interface. https://github.com/rescript-lang/rescript/pull/7779 - Fix parse error with nested record types and attributes on the field name that has the nested record type. https://github.com/rescript-lang/rescript/pull/7781 - Fix ppx resolution with package inside monorepo. https://github.com/rescript-lang/rescript/pull/7776 diff --git a/analysis/src/SemanticTokens.ml b/analysis/src/SemanticTokens.ml index ad22221186..7868f01cd1 100644 --- a/analysis/src/SemanticTokens.ml +++ b/analysis/src/SemanticTokens.ml @@ -247,12 +247,32 @@ let command ~debug ~emitter ~path = match e.pexp_desc with | Pexp_ident {txt = lid; loc} -> if lid <> Lident "not" then - if not loc.loc_ghost then - emitter - |> emitLongident ~pos:(Loc.start loc) - ~posEnd:(Some (Loc.end_ loc)) - ~lid ~debug; - Ast_iterator.default_iterator.expr iterator e + if not loc.loc_ghost then ( + (* Don't emit semantic tokens for identifiers not present in source code *) + let should_emit = + match lid with + (* Array spread (`...`) is converted to `Belt.Array.concatMany` with `@res.spread` decorator *) + | Ldot (Ldot (Lident "Belt", "Array"), "concatMany") -> + let has_spread_attr = + e.pexp_attributes + |> List.exists (fun ({Location.txt}, _) -> txt = "res.spread") + in + not has_spread_attr + (* Dict syntax (`dict{...}`) is converted to `Primitive_dict.make` *) + | Ldot (Lident "Primitive_dict", "make") -> false + | Lident "Primitive_dict" -> false + (* Array access (`arr[index]`) is converted to `Array.get` *) + | Ldot (Lident "Array", "get") -> false + (* Array mutation (`arr[index]`) is converted to `Array.set` *) + | Ldot (Lident "Array", "set") -> false + | _ -> true + in + if should_emit then + emitter + |> emitLongident ~pos:(Loc.start loc) + ~posEnd:(Some (Loc.end_ loc)) + ~lid ~debug; + Ast_iterator.default_iterator.expr iterator e) | Pexp_jsx_element (Jsx_unary_element {jsx_unary_element_tag_name = lident}) -> (* diff --git a/tests/analysis_tests/tests/not_compiled/SemanticTokensArray.res b/tests/analysis_tests/tests/not_compiled/SemanticTokensArray.res new file mode 100644 index 0000000000..3e172fa30e --- /dev/null +++ b/tests/analysis_tests/tests/not_compiled/SemanticTokensArray.res @@ -0,0 +1,3 @@ +let xs = [1, 2] +let ys = [...xs, 3] +//^sem diff --git a/tests/analysis_tests/tests/not_compiled/SemanticTokensArrayAccess.res b/tests/analysis_tests/tests/not_compiled/SemanticTokensArrayAccess.res new file mode 100644 index 0000000000..64e62244cc --- /dev/null +++ b/tests/analysis_tests/tests/not_compiled/SemanticTokensArrayAccess.res @@ -0,0 +1,3 @@ +let x = xs[0] +let x = xs[index] +//^sem diff --git a/tests/analysis_tests/tests/not_compiled/SemanticTokensArrayMutation.res b/tests/analysis_tests/tests/not_compiled/SemanticTokensArrayMutation.res new file mode 100644 index 0000000000..e195ab10b6 --- /dev/null +++ b/tests/analysis_tests/tests/not_compiled/SemanticTokensArrayMutation.res @@ -0,0 +1,2 @@ +xs[0] = 42 +//^sem diff --git a/tests/analysis_tests/tests/not_compiled/SemanticTokensDict.res b/tests/analysis_tests/tests/not_compiled/SemanticTokensDict.res new file mode 100644 index 0000000000..529b636667 --- /dev/null +++ b/tests/analysis_tests/tests/not_compiled/SemanticTokensDict.res @@ -0,0 +1,2 @@ +let d = dict{"foo": bar} +//^sem diff --git a/tests/analysis_tests/tests/not_compiled/expected/SemanticTokensArray.res.txt b/tests/analysis_tests/tests/not_compiled/expected/SemanticTokensArray.res.txt new file mode 100644 index 0000000000..92a36a9961 --- /dev/null +++ b/tests/analysis_tests/tests/not_compiled/expected/SemanticTokensArray.res.txt @@ -0,0 +1 @@ +{"data":[0,4,2,1,0,1,4,2,1,0,0,9,2,1,0]} diff --git a/tests/analysis_tests/tests/not_compiled/expected/SemanticTokensArrayAccess.res.txt b/tests/analysis_tests/tests/not_compiled/expected/SemanticTokensArrayAccess.res.txt new file mode 100644 index 0000000000..858e9ef372 --- /dev/null +++ b/tests/analysis_tests/tests/not_compiled/expected/SemanticTokensArrayAccess.res.txt @@ -0,0 +1 @@ +{"data":[0,4,1,1,0,0,4,2,1,0,1,4,1,1,0,0,4,2,1,0,0,3,5,1,0]} diff --git a/tests/analysis_tests/tests/not_compiled/expected/SemanticTokensArrayMutation.res.txt b/tests/analysis_tests/tests/not_compiled/expected/SemanticTokensArrayMutation.res.txt new file mode 100644 index 0000000000..4d3810f43b --- /dev/null +++ b/tests/analysis_tests/tests/not_compiled/expected/SemanticTokensArrayMutation.res.txt @@ -0,0 +1 @@ +{"data":[0,0,2,1,0]} diff --git a/tests/analysis_tests/tests/not_compiled/expected/SemanticTokensDict.res.txt b/tests/analysis_tests/tests/not_compiled/expected/SemanticTokensDict.res.txt new file mode 100644 index 0000000000..747a90d8b3 --- /dev/null +++ b/tests/analysis_tests/tests/not_compiled/expected/SemanticTokensDict.res.txt @@ -0,0 +1 @@ +{"data":[0,4,1,1,0,0,16,3,1,0]}