From 3d14a14f3fd750b9aedcde1cad36b52b54e147f4 Mon Sep 17 00:00:00 2001 From: Hakan Nilsson Date: Wed, 18 Sep 2024 11:30:33 +0200 Subject: [PATCH] Replace jsx with stdlib json --- apps/els_core/src/els_client.erl | 2 +- apps/els_core/src/els_core.app.src | 1 - apps/els_core/src/els_jsonrpc.erl | 21 +++++++------------ apps/els_core/src/els_protocol.erl | 15 ++++++------- apps/els_core/src/els_stdio.erl | 12 +++++------ apps/els_core/src/els_utils.erl | 13 +++++++++++- .../els_lsp/src/els_eqwalizer_diagnostics.erl | 2 +- apps/els_lsp/test/els_diagnostics_SUITE.erl | 2 +- apps/els_lsp/test/els_hover_SUITE.erl | 6 ++++-- rebar.config | 2 +- rebar.lock | 6 +++--- 11 files changed, 45 insertions(+), 37 deletions(-) diff --git a/apps/els_core/src/els_client.erl b/apps/els_core/src/els_client.erl index edf198eb9..0b49bc1da 100644 --- a/apps/els_core/src/els_client.erl +++ b/apps/els_core/src/els_client.erl @@ -290,7 +290,7 @@ init(#{io_device := IoDevice}) -> [], IoDevice, fun handle_responses/1, - els_jsonrpc:default_opts() + fun els_utils:json_decode_with_atom_keys/1 ], _Pid = proc_lib:spawn_link(els_stdio, loop, Args), State = #state{io_device = IoDevice}, diff --git a/apps/els_core/src/els_core.app.src b/apps/els_core/src/els_core.app.src index 30279e4ac..91b1698f4 100644 --- a/apps/els_core/src/els_core.app.src +++ b/apps/els_core/src/els_core.app.src @@ -5,7 +5,6 @@ {applications, [ kernel, stdlib, - jsx, yamerl, redbug ]}, diff --git a/apps/els_core/src/els_jsonrpc.erl b/apps/els_core/src/els_jsonrpc.erl index 5deb0c8da..fa0117f29 100644 --- a/apps/els_core/src/els_jsonrpc.erl +++ b/apps/els_core/src/els_jsonrpc.erl @@ -7,7 +7,6 @@ %% Exports %%============================================================================== -export([ - default_opts/0, split/1, split/2 ]). @@ -26,18 +25,18 @@ %%============================================================================== -spec split(binary()) -> {[map()], binary()}. split(Data) -> - split(Data, default_opts()). + split(Data, fun els_utils:json_decode_with_atom_keys/1). --spec split(binary(), [any()]) -> {[map()], binary()}. -split(Data, DecodeOpts) -> - split(Data, DecodeOpts, []). +-spec split(binary(), fun()) -> {[map()], binary()}. +split(Data, Decoder) -> + split(Data, Decoder, []). --spec split(binary(), [any()], [map()]) -> {[map()], binary()}. -split(Data, DecodeOpts, Responses) -> +-spec split(binary(), fun(), [map()]) -> {[map()], binary()}. +split(Data, Decoder, Responses) -> case peel_content(Data) of {ok, Body, Rest} -> - Response = jsx:decode(Body, DecodeOpts), - split(Rest, DecodeOpts, [Response | Responses]); + Response = Decoder(Body), + split(Rest, Decoder, [Response | Responses]); {more, _Length} -> {lists:reverse(Responses), Data} end. @@ -74,7 +73,3 @@ peel_headers(Data, Headers) -> {error, Reason} -> erlang:error(Reason, [Data, Headers]) end. - --spec default_opts() -> [any()]. -default_opts() -> - [return_maps, {labels, atom}]. diff --git a/apps/els_core/src/els_protocol.erl b/apps/els_core/src/els_protocol.erl index cad7f3634..5dafe568f 100644 --- a/apps/els_core/src/els_protocol.erl +++ b/apps/els_core/src/els_protocol.erl @@ -34,7 +34,7 @@ notification(Method, Params) -> method => Method, params => Params }, - content(jsx:encode(Message)). + content(Message). -spec request(number(), binary()) -> binary(). request(RequestId, Method) -> @@ -43,7 +43,7 @@ request(RequestId, Method) -> method => Method, id => RequestId }, - content(jsx:encode(Message)). + content(Message). -spec request(number(), binary(), any()) -> binary(). request(RequestId, Method, Params) -> @@ -53,7 +53,7 @@ request(RequestId, Method, Params) -> id => RequestId, params => Params }, - content(jsx:encode(Message)). + content(Message). -spec response(number(), any()) -> binary(). response(RequestId, Result) -> @@ -63,7 +63,7 @@ response(RequestId, Result) -> result => Result }, ?LOG_DEBUG("[Response] [message=~p]", [Message]), - content(jsx:encode(Message)). + content(Message). -spec error(number(), any()) -> binary(). error(RequestId, Error) -> @@ -73,7 +73,7 @@ error(RequestId, Error) -> error => Error }, ?LOG_DEBUG("[Response] [message=~p]", [Message]), - content(jsx:encode(Message)). + content(Message). %%============================================================================== %% Data Structures @@ -88,8 +88,9 @@ range(#{from := {FromL, FromC}, to := {ToL, ToC}}) -> %%============================================================================== %% Internal Functions %%============================================================================== --spec content(binary()) -> binary(). -content(Body) -> +-spec content(map()) -> binary(). +content(Message) -> + Body = list_to_binary(json:encode(Message)), els_utils:to_binary([headers(Body), "\r\n", Body]). -spec headers(binary()) -> iolist(). diff --git a/apps/els_core/src/els_stdio.erl b/apps/els_core/src/els_stdio.erl index 33adadd2d..fa8264305 100644 --- a/apps/els_core/src/els_stdio.erl +++ b/apps/els_core/src/els_stdio.erl @@ -27,7 +27,7 @@ init({Cb, IoDevice}) -> ok = io:setopts(IoDevice, [binary, {encoding, latin1}]), {ok, Server} = application:get_env(els_core, server), ok = Server:set_io_device(IoDevice), - ?MODULE:loop([], IoDevice, Cb, [return_maps]). + ?MODULE:loop([], IoDevice, Cb, fun json:decode/1). -spec send(atom() | pid(), binary()) -> ok. send(IoDevice, Payload) -> @@ -37,8 +37,8 @@ send(IoDevice, Payload) -> %% Listener loop function %%============================================================================== --spec loop([binary()], any(), function(), [any()]) -> no_return(). -loop(Lines, IoDevice, Cb, JsonOpts) -> +-spec loop([binary()], any(), function(), fun()) -> no_return(). +loop(Lines, IoDevice, Cb, JsonDecoder) -> case io:get_line(IoDevice, "") of <<"\n">> -> Headers = parse_headers(Lines), @@ -46,9 +46,9 @@ loop(Lines, IoDevice, Cb, JsonOpts) -> Length = binary_to_integer(BinLength), %% Use file:read/2 since it reads bytes {ok, Payload} = file:read(IoDevice, Length), - Request = jsx:decode(Payload, JsonOpts), + Request = JsonDecoder(Payload), Cb([Request]), - ?MODULE:loop([], IoDevice, Cb, JsonOpts); + ?MODULE:loop([], IoDevice, Cb, JsonDecoder); eof -> Cb([ #{ @@ -57,7 +57,7 @@ loop(Lines, IoDevice, Cb, JsonOpts) -> } ]); Line -> - ?MODULE:loop([Line | Lines], IoDevice, Cb, JsonOpts) + ?MODULE:loop([Line | Lines], IoDevice, Cb, JsonDecoder) end. -spec parse_headers([binary()]) -> [{binary(), binary()}]. diff --git a/apps/els_core/src/els_utils.erl b/apps/els_core/src/els_utils.erl index b312d0635..6c26a15a7 100644 --- a/apps/els_core/src/els_utils.erl +++ b/apps/els_core/src/els_utils.erl @@ -27,7 +27,8 @@ is_windows/0, system_tmp_dir/0, race/2, - uniq/1 + uniq/1, + json_decode_with_atom_keys/1 ]). %%============================================================================== @@ -320,6 +321,12 @@ uniq([X | Xs], M) -> uniq([], _) -> []. +-spec json_decode_with_atom_keys(binary()) -> map(). +json_decode_with_atom_keys(Binary) -> + Push = fun(Key, Value, Acc) -> [{binary_to_atom(Key), Value} | Acc] end, + {Result, ok, <<>>} = json:decode(Binary, ok, #{object_push => Push}), + Result. + %%============================================================================== %% Internal functions %%============================================================================== @@ -784,4 +791,8 @@ camel_case_test() -> ?assertEqual(<<"FooBarBaz">>, camel_case(<<"foo_bar_baz">>)), ?assertEqual(<<"FooBarBaz">>, camel_case(<<"'foo_bar_baz'">>)). +json_decode_with_atom_keys_test() -> + Json = list_to_binary(json:encode(#{foo => bar})), + ?assertEqual(#{foo => <<"bar">>}, json_decode_with_atom_keys(Json)). + -endif. diff --git a/apps/els_lsp/src/els_eqwalizer_diagnostics.erl b/apps/els_lsp/src/els_eqwalizer_diagnostics.erl index 172d56cc2..2e6509495 100644 --- a/apps/els_lsp/src/els_eqwalizer_diagnostics.erl +++ b/apps/els_lsp/src/els_eqwalizer_diagnostics.erl @@ -63,7 +63,7 @@ eqwalize(Project, Module) -> -spec make_diagnostic(binary()) -> {true, els_diagnostics:diagnostic()} | false. make_diagnostic(Message) -> - try jsx:decode(els_utils:to_binary(Message)) of + try json:decode(els_utils:to_binary(Message)) of #{ <<"relative_path">> := _RelativePath, <<"diagnostic">> := diff --git a/apps/els_lsp/test/els_diagnostics_SUITE.erl b/apps/els_lsp/test/els_diagnostics_SUITE.erl index 1ae1cf2ed..50150566b 100644 --- a/apps/els_lsp/test/els_diagnostics_SUITE.erl +++ b/apps/els_lsp/test/els_diagnostics_SUITE.erl @@ -148,7 +148,7 @@ init_per_testcase(TestCase, Config) when TestCase =:= eqwalizer -> meck:expect(els_eqwalizer_diagnostics, is_default, 0, true), Diagnostics = [ els_utils:to_list( - jsx:encode(#{ + json:encode(#{ <<"diagnostic">> => #{ <<"code">> => <<"eqwalizer">>, diff --git a/apps/els_lsp/test/els_hover_SUITE.erl b/apps/els_lsp/test/els_hover_SUITE.erl index aceae9601..343e79178 100644 --- a/apps/els_lsp/test/els_hover_SUITE.erl +++ b/apps/els_lsp/test/els_hover_SUITE.erl @@ -642,8 +642,10 @@ memoize(Config) -> #{entries := Entries} = Item, %% JSON RPC - Encoded = jsx:encode(#{contents => els_markup_content:new(Entries)}), - Result = jsx:decode(Encoded, [{labels, atom}]), + Encoded = list_to_binary( + json:encode(#{contents => els_markup_content:new(Entries)}) + ), + Result = els_utils:json_decode_with_atom_keys(Encoded), ?assertEqual(Expected, Result), ok. diff --git a/rebar.config b/rebar.config index e1f198f47..099d23b32 100644 --- a/rebar.config +++ b/rebar.config @@ -7,7 +7,7 @@ ]}. {deps, [ - {jsx, "3.0.0"}, + {json_polyfill, "0.1.4"}, {redbug, "2.0.6"}, {yamerl, {git, "https://github.com/erlang-ls/yamerl.git", diff --git a/rebar.lock b/rebar.lock index 0fb5def17..a0c24d88b 100644 --- a/rebar.lock +++ b/rebar.lock @@ -9,7 +9,7 @@ {git,"https://github.com/josefs/Gradualizer.git", {ref,"3021d29d82741399d131e3be38d2a8db79d146d4"}}, 0}, - {<<"jsx">>,{pkg,<<"jsx">>,<<"3.0.0">>},0}, + {<<"json_polyfill">>,{pkg,<<"json_polyfill">>,<<"0.1.4">>},0}, {<<"katana_code">>,{pkg,<<"katana_code">>,<<"2.1.1">>},1}, {<<"providers">>,{pkg,<<"providers">>,<<"1.8.1">>},1}, {<<"quickrand">>,{pkg,<<"quickrand">>,<<"2.0.7">>},1}, @@ -30,7 +30,7 @@ {<<"ephemeral">>, <<"B3E57886ADD5D90C82FE3880F5954978222A122CB8BAA123667401BBAAEC51D6">>}, {<<"erlfmt">>, <<"5DDECA120A6E8E0A0FAB7D0BB9C2339D841B1C9E51DD135EE583256DEF20DE25">>}, {<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}, - {<<"jsx">>, <<"20A170ABD4335FC6DB24D5FAD1E5D677C55DADF83D1B20A8A33B5FE159892A39">>}, + {<<"json_polyfill">>, <<"ED9AD7A8CBDB8D1F1E59E22CDAE23A153A5BB93B5529AEBAEB189CA4B4C536C8">>}, {<<"katana_code">>, <<"9AC515E6B5AE4903CD7B6C9161ABFBA49B610B6F3E19E8F0542802A4316C2405">>}, {<<"providers">>, <<"70B4197869514344A8A60E2B2A4EF41CA03DEF43CFB1712ECF076A0F3C62F083">>}, {<<"quickrand">>, <<"D2BD76676A446E6A058D678444B7FDA1387B813710D1AF6D6E29BB92186C8820">>}, @@ -46,7 +46,7 @@ {<<"ephemeral">>, <<"4B293D80F75F9C4575FF4B9C8E889A56802F40B018BF57E74F19644EFEE6C850">>}, {<<"erlfmt">>, <<"3933A40CFBE790AD94E5B650B36881DE70456319263C1479B556E9AFDBD80C75">>}, {<<"getopt">>, <<"53E1AB83B9CEB65C9672D3E7A35B8092E9BDC9B3EE80721471A161C10C59959C">>}, - {<<"jsx">>, <<"37BECA0435F5CA8A2F45F76A46211E76418FBEF80C36F0361C249FC75059DC6D">>}, + {<<"json_polyfill">>, <<"48C397EE2547FA459EDE01A30EC0E85717ABED3010867A63EEAAC5F203274303">>}, {<<"katana_code">>, <<"0680F33525B9A882E6F4D3022518B15C46F648BD7B0DBE86900980FE1C291404">>}, {<<"providers">>, <<"E45745ADE9C476A9A469EA0840E418AB19360DC44F01A233304E118A44486BA0">>}, {<<"quickrand">>, <<"B8ACBF89A224BC217C3070CA8BEBC6EB236DBE7F9767993B274084EA044D35F0">>},