diff --git a/lib/livebook/intellisense/docs.ex b/lib/livebook/intellisense/docs.ex index e3468f22c..bbd8e9675 100644 --- a/lib/livebook/intellisense/docs.ex +++ b/lib/livebook/intellisense/docs.ex @@ -143,4 +143,21 @@ defmodule Livebook.Intellisense.Docs do # loads elixir.beam, so we explicitly list it. defp ensure_loaded?(Elixir), do: false defp ensure_loaded?(module), do: Code.ensure_loaded?(module) + + @doc """ + Checks if the module has any documentation. + """ + @spec any_docs?(module()) :: boolean() + def any_docs?(module) do + case Code.fetch_docs(module) do + {:docs_v1, _, _, _, %{}, _, _} -> + true + + {:docs_v1, _, _, _, _, _, docs} -> + Enum.any?(docs, &match?({_, _, _, %{}, _}, &1)) + + _ -> + false + end + end end diff --git a/lib/livebook/runtime/evaluator.ex b/lib/livebook/runtime/evaluator.ex index 612e05e7b..167f6994c 100644 --- a/lib/livebook/runtime/evaluator.ex +++ b/lib/livebook/runtime/evaluator.ex @@ -456,7 +456,9 @@ defmodule Livebook.Runtime.Evaluator do end if ebin_path() do - Livebook.Runtime.Evaluator.Doctests.run(new_context.env.context_modules) + new_context.env.context_modules + |> Enum.filter(&Livebook.Intellisense.Docs.any_docs?/1) + |> Livebook.Runtime.Evaluator.Doctests.run() end state = put_context(state, ref, new_context) diff --git a/lib/livebook/runtime/evaluator/doctests.ex b/lib/livebook/runtime/evaluator/doctests.ex index fc6e543e6..3810525ca 100644 --- a/lib/livebook/runtime/evaluator/doctests.ex +++ b/lib/livebook/runtime/evaluator/doctests.ex @@ -36,7 +36,18 @@ defmodule Livebook.Runtime.Evaluator.Doctests do end defp define_test_module(modules) do - name = Module.concat([LivebookDoctest | modules]) + id = + modules + |> Enum.sort() + |> Enum.map_join("-", fn module -> + module + |> Atom.to_string() + |> String.replace_prefix("Elixir.", "") + end) + |> :erlang.md5() + |> Base.encode32(padding: false) + + name = Module.concat([LivebookDoctest, "TestModule#{id}"]) try do defmodule name do diff --git a/test/livebook/hubs/docs_test.exs b/test/livebook/hubs/docs_test.exs new file mode 100644 index 000000000..e18b44fa9 --- /dev/null +++ b/test/livebook/hubs/docs_test.exs @@ -0,0 +1,13 @@ +defmodule Livebook.Intellisense.DocsTest do + use ExUnit.Case, async: true + + alias Livebook.Intellisense.Docs + + test "any_docs?/1" do + refute Docs.any_docs?(Livebook.TestModules.Docs.Without) + refute Docs.any_docs?(Livebook.TestModules.Docs.ModuleHidden) + refute Docs.any_docs?(Livebook.TestModules.Docs.FunctionHidden) + assert Docs.any_docs?(Livebook.TestModules.Docs.Module) + assert Docs.any_docs?(Livebook.TestModules.Docs.Function) + end +end diff --git a/test/support/test_modules/docs.ex b/test/support/test_modules/docs.ex new file mode 100644 index 000000000..cdc67f1e2 --- /dev/null +++ b/test/support/test_modules/docs.ex @@ -0,0 +1,20 @@ +defmodule Livebook.TestModules.Docs.Without do +end + +defmodule Livebook.TestModules.Docs.ModuleHidden do + @moduledoc false +end + +defmodule Livebook.TestModules.Docs.Module do + @moduledoc "Hello." +end + +defmodule Livebook.TestModules.Docs.FunctionHidden do + @doc false + def hello(), do: "hello" +end + +defmodule Livebook.TestModules.Docs.Function do + @doc "Hello." + def hello(), do: "hello" +end