diff --git a/.gitignore b/.gitignore index c90b3a7ef..cac37ef18 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ rebar.lock tmp/ _packages elvis +emqx_dialyzer_*_plt diff --git a/README-CN.md b/README-CN.md index 3d7843ed7..045a089ee 100644 --- a/README-CN.md +++ b/README-CN.md @@ -62,6 +62,17 @@ cd _rel/emqx && ./bin/emqx console *EMQ X* 启动,可以使用浏览器访问 http://localhost:18083 来查看 Dashboard。 +### 静态分析(Dialyzer) +##### 分析所有应用程序 +``` +make dialyzer +``` + +##### 要分析特定的应用程序,(用逗号分隔的应用程序列表) +``` +DIALYZER_ANALYSE_APP=emqx_lwm2m,emqx_auth_jwt,emqx_auth_ldap make dialyzer +``` + ## FAQ 访问 [EMQ X FAQ](https://docs.emqx.io/broker/latest/cn/faq/faq.html) 以获取常见问题的帮助。 diff --git a/README-JP.md b/README-JP.md index 665f18b1b..de0751600 100644 --- a/README-JP.md +++ b/README-JP.md @@ -62,6 +62,17 @@ cd _rel/emqx && ./bin/emqx console *EMQ X* ブローカーを起動したら、ブラウザで http://localhost:18083 にアクセスしてダッシュボードを表示できます。 +### ダイアライザー +##### すべてのアプリを分析するには +``` +make dialyzer +``` + +##### 特定のアプリを分析するには(アプリのコンマ区切りリスト) +``` +DIALYZER_ANALYSE_APP=emqx_lwm2m,emqx_auth_jwt,emqx_auth_ldap make dialyzer +``` + ## FAQ よくある質問については、[EMQ X FAQ](https://docs.emqx.io/broker/latest/en/faq/faq.html)にアクセスしてください。 diff --git a/README.md b/README.md index 6479c2651..d7f162073 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,17 @@ examples NOTE: Do *NOT* use full (relative) path to SUITE files like this `--suite apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl`, because it will lead to a full copy of `apps` dir into `_buid/test/lib/emqx`. +### Dialyzer +##### To Analyze all the apps +``` +make dialyzer +``` + +##### To Analyse specific apps, (list of comma separated apps) +``` +DIALYZER_ANALYSE_APP=emqx_lwm2m,emqx_auth_jwt,emqx_auth_ldap make dialyzer +``` + ## FAQ Visiting [EMQ X FAQ](https://docs.emqx.io/broker/latest/en/faq/faq.html) to get help of common problems. diff --git a/rebar.config b/rebar.config index 0d93463b7..5991db4f3 100644 --- a/rebar.config +++ b/rebar.config @@ -19,7 +19,14 @@ {xref_checks,[undefined_function_calls,undefined_functions,locals_not_used, deprecated_function_calls,warnings_as_errors, deprecated_functions]}. -{dialyzer, [{warnings, [unmatched_returns, error_handling, race_conditions]}]}. +{dialyzer, [ + {warnings, [unmatched_returns, error_handling, race_conditions]}, + {plt_location, "."}, + {plt_prefix, "emqx_dialyzer"}, + {plt_apps, all_apps}, + {statistics, true} + ] +}. {cover_enabled, true}. {cover_opts, [verbose]}. diff --git a/rebar.config.erl b/rebar.config.erl index 383be2e71..b203b1259 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -4,7 +4,7 @@ do(Dir, CONFIG) -> ok = compile_and_load_pase_transforms(Dir), - dump(deps(CONFIG) ++ config()). + dump(deps(CONFIG) ++ dialyzer(CONFIG) ++ config()). bcrypt() -> {bcrypt, {git, "https://github.com/emqx/erlang-bcrypt.git", {branch, "0.6.0"}}}. @@ -268,3 +268,33 @@ str(B) when is_binary(B) -> unicode:characters_to_list(B, utf8). erl_opts_i() -> [{i, "apps"}] ++ [{i, Dir} || Dir <- filelib:wildcard(filename:join(["apps", "**", "include"]))]. + +dialyzer(Config) -> + {dialyzer, OldDialyzerConfig} = lists:keyfind(dialyzer, 1, Config), + + AppsToAnalyse = case os:getenv("DIALYZER_ANALYSE_APP") of + false -> + []; + Value -> + [ list_to_atom(App) || App <- string:tokens(Value, ",")] + end, + + AppsDir = "apps", + AppNames = [emqx | list_dir(AppsDir)], + + KnownApps = [Name || Name <- AppsToAnalyse, lists:member(Name, AppNames)], + UnknownApps = AppsToAnalyse -- KnownApps, + io:format("Unknown Apps ~p ~n", [UnknownApps]), + + AppsToExclude = AppNames -- KnownApps, + + case length(AppsToAnalyse) > 0 of + true -> + lists:keystore(dialyzer, 1, Config, {dialyzer, OldDialyzerConfig ++ [{exclude_apps, AppsToExclude}]}); + false -> + Config + end. + +list_dir(Dir) -> + {ok, Names} = file:list_dir(Dir), + [list_to_atom(Name) || Name <- Names, filelib:is_dir(filename:join([Dir, Name]))].