Jelajahi Sumber

fix(bpapi): Use argument types from the spec

k32 4 tahun lalu
induk
melakukan
04bac16741
1 mengubah file dengan 17 tambahan dan 9 penghapusan
  1. 17 9
      apps/emqx/src/bpapi/emqx_bpapi_static_checks.erl

+ 17 - 9
apps/emqx/src/bpapi/emqx_bpapi_static_checks.erl

@@ -20,6 +20,9 @@
 
 
 -include_lib("emqx/include/logger.hrl").
 -include_lib("emqx/include/logger.hrl").
 
 
+%% Using an undocumented API here :(
+-include_lib("dialyzer/src/dialyzer.hrl").
+
 -type api_dump() :: #{{emqx_bpapi:api(), emqx_bpapi:api_version()} =>
 -type api_dump() :: #{{emqx_bpapi:api(), emqx_bpapi:api_version()} =>
                           #{ calls := [emqx_bpapi:rpc()]
                           #{ calls := [emqx_bpapi:rpc()]
                            , casts := [emqx_bpapi:rpc()]
                            , casts := [emqx_bpapi:rpc()]
@@ -128,21 +131,24 @@ typecheck_apis( #{release := CallerRelease, api := CallerAPIs, signatures := Cal
                                   setnok(),
                                   setnok(),
                                   [?ERROR("Incompatible RPC call: "
                                   [?ERROR("Incompatible RPC call: "
                                           "type of the parameter ~p of RPC call ~s on release ~p "
                                           "type of the parameter ~p of RPC call ~s on release ~p "
-                                          "is not a subtype of the target function ~s on release ~p",
+                                          "is not a subtype of the target function ~s on release ~p.~n"
+                                          "Caller type: ~s~nCallee type: ~s~n",
                                           [Var, format_call(From), CallerRelease,
                                           [Var, format_call(From), CallerRelease,
-                                           format_call(To), CalleeRelease])
-                                   || Var <- TypeErrors]
+                                           format_call(To), CalleeRelease,
+                                           erl_types:t_to_string(CallerType),
+                                           erl_types:t_to_string(CalleeType)])
+                                   || {Var, CallerType, CalleeType} <- TypeErrors]
                           end
                           end
                   end,
                   end,
                   AllCalls).
                   AllCalls).
 
 
--spec typecheck_rpc(param_types(), param_types()) -> [emqx_bpapi:var_name()].
+-spec typecheck_rpc(param_types(), param_types()) -> [{emqx_bpapi:var_name(), _Type, _Type}].
 typecheck_rpc(Caller, Callee) ->
 typecheck_rpc(Caller, Callee) ->
     maps:fold(fun(Var, CalleeType, Acc) ->
     maps:fold(fun(Var, CalleeType, Acc) ->
                       #{Var := CallerType} = Caller,
                       #{Var := CallerType} = Caller,
                       case erl_types:t_is_subtype(CallerType, CalleeType) of
                       case erl_types:t_is_subtype(CallerType, CalleeType) of
                           true  -> Acc;
                           true  -> Acc;
-                          false -> [Var|Acc]
+                          false -> [{Var, CallerType, CalleeType}|Acc]
                       end
                       end
               end,
               end,
               [],
               [],
@@ -182,7 +188,7 @@ dump(Opts) ->
     warn_nonbpapi_rpcs(NonBPAPICalls),
     warn_nonbpapi_rpcs(NonBPAPICalls),
     APIDump = collect_bpapis(BPAPICalls),
     APIDump = collect_bpapis(BPAPICalls),
     DialyzerDump = collect_signatures(PLT, APIDump),
     DialyzerDump = collect_signatures(PLT, APIDump),
-    Release = emqx_app:get_release(),
+    [Release|_] = string:split(emqx_app:get_release(), "-"),
     dump_api(#{api => APIDump, signatures => DialyzerDump, release => Release}),
     dump_api(#{api => APIDump, signatures => DialyzerDump, release => Release}),
     xref:stop(?XREF),
     xref:stop(?XREF),
     erase(bpapi_ok).
     erase(bpapi_ok).
@@ -263,9 +269,11 @@ collect_signatures(PLT, APIs) ->
 enrich({From0, To0}, {Acc0, PLT}) ->
 enrich({From0, To0}, {Acc0, PLT}) ->
     From = call_to_mfa(From0),
     From = call_to_mfa(From0),
     To   = call_to_mfa(To0),
     To   = call_to_mfa(To0),
-    case {dialyzer_plt:lookup(PLT, From), dialyzer_plt:lookup(PLT, To)} of
-        {{value, TFrom}, {value, TTo}} ->
-            Acc = Acc0#{ From => TFrom
+    case {dialyzer_plt:lookup_contract(PLT, From), dialyzer_plt:lookup(PLT, To)} of
+        {{value, #contract{args = FromArgs}}, {value, TTo}} ->
+            %% TODO: Check return type
+            FromRet = erl_types:t_any(),
+            Acc = Acc0#{ From => {FromRet, FromArgs}
                        , To   => TTo
                        , To   => TTo
                        },
                        },
             {Acc, PLT};
             {Acc, PLT};