檢視原始碼 mix xref (Mix v1.16.2)
列印模組間的交叉參考資訊。
xref
任務預期第一個參數為模式
$ mix xref MODE
所有可用的模式如下所述。
此任務會自動重新啟用,因此您可以在同一個 Mix 呼叫中多次列印資訊。
mix xref callers MODULE
列印給定模組的所有呼叫者。範例
$ mix xref callers MyMod
mix xref trace FILE
編譯給定的檔案,列出同一個應用程式內的所有依賴項。它包含每個依賴項的類型和行數。範例
$ mix xref trace lib/my_app/router.ex
可以使用 --label
選項來僅保留特定追蹤 (編譯、執行時間或匯出)。
$ mix xref trace lib/my_app/router.ex --label compile
如果您有傘式應用程式,我們也建議使用 --include-siblings
旗標來查看兄弟應用程式的依賴項。目前不支援在傘式應用程式的根目錄使用 trace
指令。
範例
想像給定的檔案為 lib/b.ex
defmodule B do
import A
A.macro()
macro()
A.fun()
fun()
def calls_macro, do: A.macro()
def calls_fun, do: A.fun()
def calls_struct, do: %A{}
end
mix xref trace
會列印
lib/b.ex:2: require A (export)
lib/b.ex:3: call A.macro/0 (compile)
lib/b.ex:4: import A.macro/0 (compile)
lib/b.ex:5: call A.fun/0 (compile)
lib/b.ex:6: call A.fun/0 (compile)
lib/b.ex:6: import A.fun/0 (compile)
lib/b.ex:7: call A.macro/0 (compile)
lib/b.ex:8: call A.fun/0 (runtime)
lib/b.ex:9: struct A (export)
mix xref graph
列印檔案依賴項圖形,其中從 A
到 B
的邊緣表示 A
(來源) 依賴於 B
(匯入)。
$ mix xref graph --format stats
接受下列選項
--exclude
- 要排除的路徑。可以重複排除多個路徑。--label
- 僅顯示具有給定標籤的關聯性。標籤為「編譯」、「匯出」和「執行時間」。預設情況下,--label
選項僅過濾列印圖形,以僅顯示具有給定標籤的關聯性。您可以傳遞--only-direct
來修剪圖形,僅保留具有標籤給定的直接關聯性的節點。還有一個稱為「編譯連接」的特殊標籤,它僅保留至少有一個傳遞依賴項的編譯時間檔案。請參閱以下「依賴類型」部分。--group
- 提供視為群組的逗號分隔路徑。群組中多個檔案的依賴項和對其的依賴項被視為單一依賴項。群組元素之間的依賴項會被忽略。當您在計算編譯和編譯連接的依賴項,而您希望將一系列檔案視為一個檔案時,這會很有用。群組使用第一個路徑列印,並加上+
字尾。可以重複使用以建立多個群組。--only-direct
- 僅保留具有--label
給定的直接關聯性的檔案--only-nodes
- 僅顯示節點名稱(沒有邊緣)。通常與--sink
標記一起使用--source
- 顯示給定來源檔案直接或間接引用的所有檔案。可以重複使用以顯示來自多個來源的參考。--sink
- 顯示直接或間接引用給定檔案的所有檔案。可以重複使用。--min-cycle-size
- 控制stats
和cycles
等格式的最小循環大小--format
- 可以設定為下列其中之一pretty
- 使用 Unicode 字元將圖形列印到終端機。每個檔案後面都會列印它所依賴的檔案。這是預設值,但 Windows 除外;plain
- 與 pretty 相同,但使用 ASCII 字元取代 Unicode 字元。這是 Windows 的預設值;stats
- 列印圖形的概括統計資料;cycles
- 列印圖形中的所有循環;dot
- 在目前目錄中產生xref_graph.dot
的 DOT 圖形描述。警告:這會覆寫先前產生的任何檔案
--output
(自 v1.15.0 起) - 可以設定為下列其中之一-
- 將輸出列印到標準輸出;路徑 - 將輸出圖形寫入給定的路徑
預設為目前目錄中的
xref_graph.dot
。
當嘗試了解特定檔案中的模組如何與整個系統互動時,--source
和 --sink
選項特別有用。你可以將這些選項與 --label
和 --only-nodes
結合使用,以取得具有特定屬性的所有檔案,例如
# To show all compile-time relationships
$ mix xref graph --label compile
# To get the tree that depend on lib/foo.ex at compile time
$ mix xref graph --label compile --sink lib/foo.ex
# To get all files that depend on lib/foo.ex at compile time
$ mix xref graph --label compile --sink lib/foo.ex --only-nodes
# To get all paths between two files
$ mix xref graph --source lib/foo.ex --sink lib/bar.ex
# To show general statistics about the graph
$ mix xref graph --format stats
了解列印的圖形
當 mix xref graph
執行時,它會列印以下格式的樹狀結構。想像以下程式碼
# lib/a.ex
defmodule A do
IO.puts B.hello()
end
# lib/b.ex
defmodule B do
def hello, do: C.world()
end
# lib/c.ex
defmodule C do
def world, do: "hello world"
end
它會列印
$ mix xref graph
lib/a.ex
└── lib/b.ex (compile)
lib/b.ex
└── lib/c.ex
lib/c.ex
這個樹狀結構表示 lib/a.ex
在編譯時依賴於 lib/b.ex
。而 lib/b.ex
在執行時依賴於 lib/c.ex
。這通常是有問題的,因為如果 lib/c.ex
發生變更,lib/a.ex
也必須重新編譯,這是因為這個間接的編譯時依賴關係。當你傳遞 --label compile
時,圖形只會顯示編譯時依賴關係
$ mix xref graph --label compile
lib/a.ex
└── lib/b.ex (compile)
--label compile
旗標會移除所有非編譯時依賴關係。然而,這可能會產生誤導,因為擁有直接的編譯時依賴關係不一定會造成問題。如上所述,最大的問題是傳遞性的編譯時依賴關係。你可以使用 --label compile-connected
取得所有會導致傳遞性編譯時依賴關係的編譯時依賴關係
$ mix xref graph --label compile-connected
lib/a.ex
└── lib/b.ex (compile)
上述內容表示 lib/a.ex
依賴於 lib/b.ex
,並且會導致傳遞性編譯時依賴關係 - 我們知道,lib/a.ex
也依賴於 lib/c.ex
。我們可以透過將 lib/b.ex
傳遞為 --source
給 mix xref graph
來擷取這些傳遞性依賴關係
$ mix xref graph --source lib/b.ex
lib/b.ex
└── lib/c.ex
類似地,你可以使用 --label compile
和 --sink
旗標來找出所有一旦接收端發生變更就會重新編譯的編譯時依賴關係
$ mix xref graph --label compile --sink lib/c.ex
lib/a.ex
└── lib/b.ex (compile)
如果你有一個 umbrella 應用程式,我們也建議使用 --include-siblings
旗標,以查看來自兄弟應用程式的依賴關係。當在 umbrella 根目錄呼叫時,graph
指令會列出所有 umbrella 子項目的所有檔案,而不會有任何命名空間。
相依類型
Elixir 追蹤模組間三種類型的相依性:編譯、匯出和執行時期。如果模組對另一個模組有編譯時期相依性,則呼叫者模組必須在被呼叫者變更時重新編譯。編譯時期相依性通常在使用巨集或在模組主體中呼叫函式(在函式外)時加入。你可以透過執行 mix xref trace path/to/file.ex
來列出檔案中的所有相依性。
匯出相依性是對模組 API 的編譯時期相依性,即結構和其公開定義。例如,如果你匯入一個模組但只使用其函式,則為匯出相依性。如果你使用結構,則也是匯出相依性。匯出相依性只有在模組 API 變更時才會重新編譯。不過,請注意,編譯時期相依性具有比匯出更高的優先順序。因此,如果你匯入一個模組並使用其巨集,則為編譯時期相依性。
執行時期相依性會在你於函式中呼叫另一個模組時加入。具有執行時期相依性的模組在被呼叫者變更時不必重新編譯,除非它們之間存在傳遞編譯或過時的匯出時間相依性。選項 --label compile-connected
可用於找出第一個案例。
共用選項
這些選項在所有模式中共用
--fail-above
- 如果相關指標高於給定的閾值,則產生失敗。適用於所有模式,除了mix xref graph --format stats
。--include-siblings
- 在報告中包含在目前專案中將:in_umbrella
設為 true 的相依性。這可用於找出呼叫者或分析專案之間的圖形(僅適用於trace
子指令)--no-compile
- 即使檔案需要編譯,也不編譯--no-deps-check
- 不檢查相依性--no-archives-check
- 不檢查封存檔--no-elixir-version-check
- 不檢查 mix.exs 中的 Elixir 版本
摘要
函數
傳回專案中所有執行時期函數呼叫的資訊清單。
函數
@spec calls(keyword()) :: [ %{callee: {module(), atom(), arity()}, line: integer(), file: String.t()} ]
傳回專案中所有執行時期函數呼叫的資訊清單。
清單中的每個項目都是一個具有下列金鑰的對應
:callee
- 包含呼叫的模組、函數和元數的元組:line
- 表示呼叫函數的行數的整數:file
- 表示呼叫函數的檔案的二進位檔:caller_module
- 呼叫函數的模組
此函數在雨傘專案的根目錄使用時會傳回一個空清單,因為沒有編譯清單可供萃取函數呼叫資訊。若要取得雨傘中每個子項目的函數呼叫,請在每個個別應用程式的根目錄執行函數。