-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Description
Elixir and Erlang/OTP versions
Erlang/OTP 25 [erts-13.1.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns]
Elixir 1.14.3 (compiled with Erlang/OTP 25)
Operating system
MacOS Ventura 13.4
Current behavior
The behavior of various mix xref
tools is weird, and in some cases just plain doesn't work, on umbrella apps. Here's a sample umbrella app that I did testing on: https://github.com/japhib/simple_umbrella_app
1. mix xref trace
doesn't work with relative paths
$ mix xref trace apps/app_b/lib/app_b.ex
** (Code.LoadError) could not load /Users/japhib/projects/simple_umbrella_app/apps/app_a/apps/app_b/lib/app_b.ex. Reason: enoent
(elixir 1.14.3) lib/code.ex:1826: Code.find_file!/2
(elixir 1.14.3) lib/code.ex:1521: anonymous fn/2 in Code.compile_file/2
(mix 1.14.3) lib/mix/tasks/xref.ex:471: Mix.Tasks.Xref.handle_trace/2
(mix 1.14.3) lib/mix/task.ex:421: anonymous fn/3 in Mix.Task.run_task/4
(mix 1.14.3) lib/mix/project.ex:397: Mix.Project.in_project/4
(elixir 1.14.3) lib/file.ex:1607: File.cd!/2
(mix 1.14.3) lib/mix/task.ex:577: anonymous fn/4 in Mix.Task.run_in_children_projects/2
Note that above ^ the error comes from attempting to load the path I passed in, apps/app_b/lib/app_b.ex
, under the prefix of apps/app_a
. My guess is that it tries to find the provided path in every app rather than just a single one.
When I provide an absolute path, it works fine:
$ mix xref trace /Users/japhib/projects/simple_umbrella_app/apps/app_b/lib/app_b.ex
==> app_a
/Users/japhib/projects/simple_umbrella_app/apps/app_b/lib/app_b.ex:4: struct StructInAppA (export)
/Users/japhib/projects/simple_umbrella_app/apps/app_b/lib/app_b.ex:4: alias StructInAppA (runtime)
/Users/japhib/projects/simple_umbrella_app/apps/app_b/lib/app_b.ex:9: call AppA.hello/0 (runtime)
2. mix xref graph --include-siblings
does not include dependencies on other apps
According to the docs, using the --include-siblings
flag should:
includes dependencies that have :in_umbrella set to true in the current project in the reports. This can be used to find callers or to analyze graphs between projects.
In my test project simple_umbrella_app, there is a dependency from lib/app_b.ex
on both lib/app_a.ex
and lib/struct_in_app_a.ex
. Neither of these dependencies are shown.
$ mix xref graph --include-siblings
==> app_a
lib/app_a.ex
└── lib/struct_in_app_a.ex (export)
lib/struct_in_app_a.ex
==> app_b
lib/app_b.ex
3. The --sink
and --source
options on mix xref graph
do not work
The --sink
option is supposed to show a graph of modules that reference the specified module, while the --source
option is supposed to show a graph of modules that the specified module references. This rarely works (see below) and seems to have something to do with the way the path is specified.
# app_a.ex
$ mix xref graph --sink lib/app_a.ex
** (Mix) Sinks could not be found: lib/app_a.ex
$ mix xref graph --sink apps/app_a/lib/app_a.ex
** (Mix) Sinks could not be found: apps/app_a/lib/app_a.ex
$ mix xref graph --sink /Users/japhib/projects/simple_umbrella_app/apps/app_a/lib/app_a.ex
** (Mix) Sinks could not be found: /Users/japhib/projects/simple_umbrella_app/apps/app_a/lib/app_a.ex
$ mix xref graph --source lib/app_a.ex
==> app_a
lib/app_a.ex
└── lib/struct_in_app_a.ex (export)
** (Mix) Sources could not be found: lib/app_a.ex
$ mix xref graph --source apps/app_a/lib/app_a.ex
** (Mix) Sources could not be found: apps/app_a/lib/app_a.ex
$ mix xref graph --source /Users/japhib/projects/simple_umbrella_app/apps/app_a/lib/app_a.ex
** (Mix) Sources could not be found: /Users/japhib/projects/simple_umbrella_app/apps/app_a/lib/app_a.ex
# app_b.ex
$ mix xref graph --sink lib/app_b.ex
** (Mix) Sinks could not be found: lib/app_b.ex
$ mix xref graph --sink apps/app_b/lib/app_b.ex
** (Mix) Sinks could not be found: apps/app_b/lib/app_b.ex
$ mix xref graph --sink /Users/japhib/projects/simple_umbrella_app/apps/app_b/lib/app_b.ex
** (Mix) Sinks could not be found: /Users/japhib/projects/simple_umbrella_app/apps/app_b/lib/app_b.ex
$ mix xref graph --source lib/app_b.ex
** (Mix) Sources could not be found: lib/app_b.ex
$ mix xref graph --source apps/app_b/lib/app_b.ex
** (Mix) Sources could not be found: apps/app_b/lib/app_b.ex
$ mix xref graph --source /Users/japhib/projects/simple_umbrella_app/apps/app_b/lib/app_b.ex
** (Mix) Sources could not be found: /Users/japhib/projects/simple_umbrella_app/apps/app_b/lib/app_b.ex
My unproven guess is that, like above, Mix is trying to use this path on every app rather than just the app it belongs to. At least, if it goes in alphabetical order (tries app_a, then app_b) then that would explain why above, with mix xref graph --source lib/app_a.ex
it actually does appear to work at first (when it runs on app_a), but then still prints out an error message (when it tries to run on app_b).
Expected behavior
I would expect mix xref graph
and mix xref trace
to be just as useful on umbrella apps as they are on regular/non-umbrella apps.