檢視原始碼 dialyzer (dialyzer v5.3)
Dialyzer 是一個用於 Erlang 程式的DIscrepancy AnaLYZer(差異分析器)。
Dialyzer 是一個靜態分析工具,用於識別軟體差異,例如確定的類型錯誤、因程式錯誤而無法執行的程式碼,以及單個 Erlang 模組或整個程式碼庫中不必要的測試。
Dialyzer 從除錯編譯的 BEAM 程式碼或 Erlang 原始碼開始分析。差異的檔案和行號會與差異性質的指示一起報告。Dialyzer 的分析基於成功類型化的概念,確保發出可靠的警告而不會有誤報。
從命令列使用 Dialyzer
本節簡要說明從命令列執行 Dialyzer 時可用的選項。相同的資訊可以透過在 shell 中輸入以下內容來取得
dialyzer --help
命令列版本的結束狀態
0
- 分析期間未發現問題,且未發出警告。1
- 分析期間發現問題。2
- 分析期間未發現問題,但發出了警告。
用法
dialyzer [--add_to_plt] [--apps applications] [--build_plt]
[--check_plt] [-Ddefine]* [-Dname]* [--dump_callgraph file]
[--error_location flag] [files_or_dirs] [--fullpath]
[--get_warnings] [--help] [-I include_dir]*
[--incremental] [--metrics_file] [--no_check_plt] [--no_indentation]
[--no_spec] [-o outfile] [--output_plt file] [-pa dir]* [--plt plt]
[--plt_info] [--plts plt*] [--quiet] [-r dirs] [--raw]
[--remove_from_plt] [--shell] [--src] [--statistics] [--verbose]
[--version] [--warning_apps applications] [-Wwarn]*
注意
* 表示可以多次出現該選項。
命令列版本的選項
--add_to_plt
- PLT 會擴展為也包含使用-c
和-r
指定的檔案。使用--plt
指定從哪個 PLT 開始,並使用--output_plt
指定將 PLT 放置在哪裡。請注意,如果檔案依賴於新檔案,則已包含在 PLT 中的檔案將會重新分析。此選項僅適用於 BEAM 檔案,不適用於原始碼檔案。--apps applications
- 預設情況下,警告會報告給--apps
給出的所有應用程式。但是,如果使用--warning_apps
,則只會針對--warning_apps
給出的應用程式報告警告。--apps
給出的所有應用程式,但未給--warning_apps
的應用程式,將會被分析以提供分析的上下文,但不會針對它們報告警告。例如,您可能希望使用--apps
將您依賴的程式庫包含在分析中,以便可以找到它們的使用上的差異,但只使用--warning_apps
來包含您自己的程式碼,以便只在您擁有的程式碼中報告差異。--warning_apps applications
- 此選項通常在建置或修改 PLT 時使用,例如dialyzer --build_plt --apps erts kernel stdlib mnesia ...
方便地引用與 Erlang/OTP 安裝相對應的程式庫應用程式。此選項也可以在分析期間使用以引用 Erlang/OTP 應用程式。檔案或目錄名稱也可以包含在內,例如
dialyzer --apps inets ssl ./ebin ../other_lib/ebin/my_module.beam
--build_plt
- 分析從空的 PLT 開始,並從使用-c
和-r
指定的檔案建立新的 PLT。此選項僅適用於 BEAM 檔案。若要覆寫預設的 PLT 位置,請使用--plt
或--output_plt
。--check_plt
- 檢查 PLT 的一致性,如果不是最新的,則重建它。-Dname
(或-Dname=value
) - 從原始碼分析時,將定義傳遞給 Dialyzer。(**)--dump_callgraph file
- 將呼叫圖轉儲到指定的檔案中,其格式由檔案名稱副檔名決定。支援的副檔名為:raw
、dot
和ps
。如果使用其他副檔名,則會使用預設的.raw
格式。--error_location column | line
- 使用一對{Line, Column}
或整數Line
來精確指出警告的位置。預設是使用一對{Line, Column}
。格式化後,行和列會以冒號分隔。files_or_dirs
(為了向後相容,也作為-c files_or_dirs
) - 從命令列使用 Dialyzer 來偵測指定檔案或目錄中包含.erl
或.beam
檔案的缺陷,具體取決於分析的類型。--fullpath
- 顯示發出警告的檔案的完整路徑名稱。--get_warnings
- 使 Dialyzer 即使在操作 PLT 時也發出警告。警告僅針對分析的檔案發出。--help
(或-h
) - 列印說明訊息並結束。-I include_dir
- 從原始碼分析時,將include_dir
傳遞給 Dialyzer。(**)--input_list_file file
- 分析指定檔案中列出的檔案名稱(每行一個檔案名稱)。--no_check_plt
- 執行 Dialyzer 時跳過 PLT 檢查。這在處理從不變更的已安裝 PLT 時很有用。--incremental
- 分析從現有的增量 PLT 開始,如果不存在則從頭開始建置一個增量 PLT,並執行最少量的額外分析以報告給定應用程式集中的所有問題。值得注意的是,增量 PLT 檔案與「經典」PLT 檔案不相容,反之亦然。除非給定替代的輸出增量 PLT,否則初始增量 PLT 將會更新。--no_indentation
- 格式化警告時,不要在類型、合約和 Erlang 程式碼中插入換行符號。--no_spec
- 忽略函式規格。當懷疑某些規格不正確時,這對於除錯很有用。-o outfile
(或--output outfile
) - 從命令列使用 Dialyzer 時,將分析結果傳送到指定的 outfile,而不是stdout
。--metrics_file file
- 將有關 Dialyzer 增量性的指標(例如,考慮的模組總數、自上次更新 PLT 以來變更的模組數、需要分析的模組數)寫入檔案。這對於追蹤和除錯 Dialyzer 的增量性很有用。--output_plt file
- 在建置後將 PLT 儲存在指定的檔案中。-pa dir
- 在 Erlang 的路徑中包含dir
。這在分析具有-include_lib()
指令的檔案時很有用。--plt plt
- 使用指定的 PLT 作為初始 PLT。如果在設定期間建置 PLT,則會檢查檔案的一致性。--plt_info
- 使 Dialyzer 列印有關 PLT 的資訊,然後退出。可以使用--plt(s)
指定 PLT。--plts plt*
- 合併指定的 PLT 以建立初始 PLT。這要求 PLT 是不相交的(也就是說,沒有任何模組出現在多個 PLT 中)。PLT 以通常的方式建立dialyzer --build_plt --output_plt plt_1 files_to_include ... dialyzer --build_plt --output_plt plt_n files_to_include
然後它們可以以下列任一方式使用
dialyzer files_to_analyze --plts plt_1 ... plt_n
或
dialyzer --plts plt_1 ... plt_n -- files_to_analyze
請注意第二種情況中的
--
分隔符號。--quiet
(或-q
) - 使 Dialyzer 安靜一點。-r dirs
- 與files_or_dirs
相同,但指定的目錄會遞迴搜尋包含.erl
或.beam
檔案的子目錄,具體取決於分析的類型。--raw
- 從命令列使用 Dialyzer 時,輸出原始分析結果(Erlang 術語)而不是格式化的結果。原始格式更容易進行後處理(例如,篩選警告或輸出 HTML 頁面)。--remove_from_plt
- 從 PLT 中移除使用-c
和-r
指定的檔案中的資訊。請注意,這可能會導致重新分析其餘的相依檔案。--src
- 覆寫預設值(分析 BEAM 檔案),並改為從 Erlang 原始碼開始分析。--statistics
- 列印有關執行進度的資訊(分析階段、每個階段花費的時間以及相對輸入的大小)。--verbose
- 使 Dialyzer 更詳細一點。--version
(或-v
) - 列印 Dialyzer 版本和更多資訊並結束。-Wwarn
- 一系列選擇性開啟/關閉警告的選項。(有關警告名稱的說明,請使用dialyzer -Whelp
。)請注意,選項也可以使用-dialyzer()
屬性在檔案中指定。有關詳細資訊,請參閱 在原始碼檔案中請求或隱藏警告 一節。
注意
** 定義和包含的語法與 erlc 使用的語法相同。
警告選項
-Werror_handling
(***) - 包含僅透過例外狀況返回的函式的警告。-Wextra_return
(***) - 警告其規格包含函式無法返回的類型的函式。-Wmissing_return
(***) - 警告返回不屬於規格一部分的值的函式。-Wno_behaviours
- 抑制關於行為回呼偏離已發佈建議介面的警告。-Wno_contracts
- 抑制關於無效合約的警告。-Wno_fail_call
- 抑制關於失敗呼叫的警告。-Wno_fun_app
- 抑制關於將會失敗的 fun 應用程式的警告。-Wno_improper_lists
- 抑制關於建構不當列表的警告。-Wno_match
- 抑制關於未使用或無法匹配的模式的警告。-Wno_missing_calls
- 抑制關於呼叫遺失函式的警告。-Wno_opaque
- 抑制關於違反資料類型不透明性的警告。-Wno_return
- 抑制關於永遠不會傳回值的函式的警告。-Wno_undefined_callbacks
- 抑制關於行為的回呼沒有-callback
屬性的警告。-Wno_unused
- 抑制關於未使用函式的警告。-Wno_unknown
- 抑制關於未知函式和類型的警告。預設行為是在設定退出狀態時警告未知函式和類型。從 Erlang 使用 Dialyzer 時,將會傳回關於未知函式和類型的警告。-Wunderspecs
(***) - 警告關於規格不夠精確的函式(規格嚴格來說比成功類型寬鬆)。-Wunmatched_returns
(***) - 包含針對忽略結構化傳回值或未與多個可能傳回值之一匹配的函式呼叫的警告。但是,如果可能的傳回值是原子聯合或數字聯合,則不會包含任何警告。
以下選項也可用,但不建議使用(它們主要用於 Dialyzer 開發人員和內部偵錯)
-Woverspecs
(***) - 警告關於規格過於精確的函式(規格嚴格來說比成功類型嚴格)。-Wspecdiffs
(***) - 當規格與成功類型不同時發出警告。
注意
*** 表示開啟警告而不是關閉警告的選項。
以下選項並非嚴格需要,因為它們指定了預設值。它們主要用於與 -dialyzer
屬性一起使用。如需範例,請參閱 在原始程式檔中請求或抑制警告章節。
-Wno_underspecs
- 抑制關於規格不夠精確的函式的警告(規格嚴格來說比成功類型寬鬆)。-Wno_extra_return
- 抑制關於規格中包含函式無法傳回之類型的函式的警告。-Wno_missing_return
- 抑制關於傳回值不屬於規格一部分的函式的警告。
從 Erlang 使用 Dialyzer
Dialyzer 可以直接從 Erlang 使用。選項與從命令列給定的選項類似。請參閱 從命令列使用 Dialyzer 章節。
預設 Dialyzer 選項
(主機作業系統)環境變數 ERL_COMPILER_OPTIONS
可用於提供預設 Dialyzer 選項。其值必須是有效的 Erlang 項。如果值是列表,則會直接使用。如果不是列表,則會放入列表中。
該列表會附加到給予 run/1
或命令列的任何選項。
可以使用 compile:env_compiler_options/0
擷取該列表。
目前唯一使用的選項是 error_location
選項。
Dialyzer 組態檔
Dialyzer 的組態檔也可用於擴充預設選項和直接提供給 Dialyzer 命令的選項。它通常用於避免重複選項,否則每次呼叫 Dialyzer 時都必須明確給出這些選項。
組態檔的位置可以透過 DIALYZER_CONFIG
環境變數設定,預設為 filename:basedir/3
的 user_config
中。
組態檔內容範例可能為
{incremental,
{default_apps,[stdlib,kernel,erts]},
{default_warning_apps,[stdlib]}
}.
{warnings, [no_improper_lists]}.
{add_pathsa,["/users/samwise/potatoes/ebin"]}.
{add_pathsz,["/users/smeagol/fish/ebin"]}.
在原始程式檔中請求或抑制警告
屬性 -dialyzer()
可用於透過指定函式或警告選項來關閉模組中的警告。例如,若要關閉函式 f/0
的所有警告,請加入以下程式碼行
-dialyzer({nowarn_function, f/0}).
若要關閉不當列表的警告,請將以下程式碼行加入原始程式檔
-dialyzer(no_improper_lists).
函式宣告後允許使用屬性 -dialyzer()
。允許使用警告選項或函式列表
-dialyzer([{nowarn_function, [f/0]}, no_improper_lists]).
警告選項可以限制為函式
-dialyzer({no_improper_lists, g/0}).
-dialyzer({[no_return, no_match], [g/0, h/0]}).
針對規格不夠精確的函式的警告選項 -Wunderspecs
可能會產生有用的警告,但規格嚴格來說比成功類型寬鬆的函式通常無法輕易修改為較不寬鬆。若要關閉規格不夠精確的函式 f/0
的警告,請加入以下程式碼行
-dialyzer({no_underspecs, f/0}).
如需警告選項的說明,請使用 dialyzer -Whelp
。這些選項也會列舉,請參閱 warn_option/0
類型。
屬性 -dialyzer()
也可用於開啟警告。例如,如果模組已針對未匹配的傳回值進行修正,則加入以下程式碼行有助於確保不會引入新的未匹配傳回值警告
-dialyzer(unmatched_returns).
摘要
類型
選項 from
預設為 byte_code
。選項 init_plt
和 plts
會變更預設值。
如果此選項的值為 line
,則整數 Line
將在訊息中用作 Location
。如果值為 column
,則會使用組 {Line, Column}
作為 Location
。預設值為 column
。
如需警告選項的說明,請參閱 警告選項 章節。
類型
-type dial_option() :: {files, [FileName :: file:filename()]} | {files_rec, [DirName :: file:filename()]} | {defines, [{Macro :: atom(), Value :: term()}]} | {from, src_code | byte_code} | {init_plt, FileName :: file:filename()} | {plts, [FileName :: file:filename()]} | {include_dirs, [DirName :: file:filename()]} | {output_file, FileName :: file:filename()} | {metrics_file, FileName :: file:filename()} | {module_lookup_file, FileName :: file:filename()} | {output_plt, FileName :: file:filename()} | {check_plt, boolean()} | {analysis_type, succ_typings | plt_add | plt_build | plt_check | plt_remove | incremental} | {warnings, [warn_option()]} | {get_warnings, boolean()} | {use_spec, boolean()} | {filename_opt, filename_opt()} | {callgraph_file, file:filename()} | {mod_deps_file, file:filename()} | {warning_files_rec, [DirName :: file:filename()]} | {error_location, error_location()}.
選項 from
預設為 byte_code
。選項 init_plt
和 plts
會變更預設值。
-type dial_warn_tag() ::
warn_behaviour | warn_bin_construction | warn_callgraph | warn_contract_extra_return |
warn_contract_missing_return | warn_contract_not_equal | warn_contract_range |
warn_contract_subtype | warn_contract_supertype | warn_contract_syntax | warn_contract_types |
warn_failing_call | warn_fun_app | warn_map_construction | warn_matching |
warn_non_proper_list | warn_not_called | warn_opaque | warn_overlapping_contract |
warn_return_no_exit | warn_return_only_exit | warn_undefined_callbacks | warn_unknown |
warn_umatched_return.
-type dial_warning() :: {Tag :: dial_warn_tag(), Id :: file_location(), Msg :: {atom(), [term()]}}.
-type error_location() :: column | line.
如果此選項的值為 line
,則整數 Line
將在訊息中用作 Location
。如果值為 column
,則會使用組 {Line, Column}
作為 Location
。預設值為 column
。
-type file_location() :: {File :: file:filename(), Location :: erl_anno:location()}.
-type filename_opt() :: basename | fullpath.
-type format_option() :: {indent_opt, boolean()} | {filename_opt, filename_opt()} | {error_location, error_location()}.
-type warn_option() ::
error_handling | no_behaviours | no_contracts | no_fail_call | no_fun_app |
no_improper_lists | no_match | no_missing_calls | no_opaque | no_return |
no_undefined_callbacks | no_underspecs | no_unknown | no_unused | underspecs | unknown |
unmatched_returns | overspecs | specdiffs | overlapping_contract | extra_return |
no_extra_return | missing_return | no_missing_return.
如需警告選項的說明,請參閱 警告選項 章節。
函式
-spec format_warning(Warnings) -> string() when Warnings :: dial_warning().
從 run/1
傳回的警告中取得字串。
-spec format_warning(Warnings, Options) -> string() when Warnings :: dial_warning(), Options :: filename_opt() | [format_option()].
從 run/1
傳回的警告中取得字串。
如果 indent_opt
設定為 true
(預設),則會在類型、合約和 Erlang 程式碼中插入換行符號,以提高可讀性。
如果 error_location
設定為 column
(預設),則位置格式化為 Line:Column
(如果可取得欄號),否則位置格式化為 Line
,即使可取得欄號也一樣。
-spec plt_info(Plt) -> {ok, ClassicResult | IncrementalResult} | {error, Reason} when Plt :: file:filename(), ClassicResult :: [{files, [file:filename()]}], IncrementalResult :: {incremental, [{modules, [module()]}]}, Reason :: not_valid | no_such_file | read_error.
傳回有關指定 PLT 的資訊。
-spec run(Options) -> Warnings when Options :: [dial_option()], Warnings :: [dial_warning()].
執行 Dialyzer 並傳回警告。