Repository: jeremyjh/dialyxir
Pull request #481 (2023-03-10 12:03:09)

Add `:no-umbrella` config option
In some cases you may want to place the `lockfile` in a parent folder without having an umbrella. With this extra option you avoid compilation at the parent folder which will fail since in such cases there is no `mix.exs`. If this flag is not set then the behaviour remains unchanged.


Patch:
diff --git a/README.md b/README.md
index 98fbd15..6bd96b6 100644
--- a/README.md
+++ b/README.md
@@ -371,3 +371,15 @@ dialyzer: [
 
 This option can also be set on the command line with `--list-unused-filters`. When used without
 `--ignore-exit-status`, this option will result in an error status code.
+
+#### `no_umbrella` flag
+
+Projects with lockfiles at a parent folder are treated as umbrella projects. In some cases however
+you may wish to have the lockfile on a parent folder without having an umbrella. By setting the
+`no_umbrella` flag to `true` your project will be treated as a non umbrella project:
+
+```elixir
+dialyzer: [
+  no_umbrella: true
+]
+```
diff --git a/lib/dialyxir/project.ex b/lib/dialyxir/project.ex
index 0df5b5f..d9f2b9c 100644
--- a/lib/dialyxir/project.ex
+++ b/lib/dialyxir/project.ex
@@ -109,6 +109,13 @@ defmodule Dialyxir.Project do
     Mix.Project.config()[:dialyzer][:flags] || []
   end
 
+  def no_umbrella? do
+    case dialyzer_config()[:no_umbrella] do
+      true -> true
+      _other -> false
+    end
+  end
+
   defp skip?({file, warning, line}, {file, warning, line, _}), do: true
   defp skip?({file, warning}, {file, warning, _, _}), do: true
   defp skip?({file}, {file, _, _, _}), do: true
diff --git a/lib/mix/tasks/dialyzer.ex b/lib/mix/tasks/dialyzer.ex
index 9f02390..07e00a5 100644
--- a/lib/mix/tasks/dialyzer.ex
+++ b/lib/mix/tasks/dialyzer.ex
@@ -295,7 +295,10 @@ defmodule Mix.Tasks.Dialyzer do
   end
 
   defp in_child? do
-    String.contains?(Mix.Project.config()[:lockfile], "..")
+    case Project.no_umbrella?() do
+      true -> false
+      false -> String.contains?(Mix.Project.config()[:lockfile], "..")
+    end
   end
 
   defp no_plt? do


Test patch:
diff --git a/test/dialyxir/project_test.exs b/test/dialyxir/project_test.exs
index 03171b5..259dcfd 100644
--- a/test/dialyxir/project_test.exs
+++ b/test/dialyxir/project_test.exs
@@ -184,4 +184,14 @@ defmodule Dialyxir.ProjectTest do
       assert Project.list_unused_filters?(list_unused_filters: nil)
     end)
   end
+
+  test "no_umbrella? works as expected" do
+    in_project(:umbrella, fn ->
+      refute Project.no_umbrella?()
+    end)
+
+    in_project(:no_umbrella, fn ->
+      assert Project.no_umbrella?()
+    end)
+  end
 end
diff --git a/test/fixtures/no_umbrella/mix.exs b/test/fixtures/no_umbrella/mix.exs
new file mode 100644
index 0000000..ea9441a
--- /dev/null
+++ b/test/fixtures/no_umbrella/mix.exs
@@ -0,0 +1,23 @@
+defmodule NoUmbrella.Mixfile do
+  use Mix.Project
+
+  def project do
+    [
+      app: :no_umbrella,
+      version: "0.1.0",
+      lockfile: "../mix.lock",
+      elixir: "~> 1.3",
+      build_embedded: Mix.env() == :prod,
+      start_permanent: Mix.env() == :prod,
+      deps: [],
+      dialyzer: [no_umbrella: true]
+    ]
+  end
+
+  # Configuration for the OTP application
+  #
+  # Type "mix help compile.app" for more information
+  def application do
+    [applications: [:logger, :public_key]]
+  end
+end