Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85827007
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
5 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/pleroma/docs/generator.ex b/lib/pleroma/docs/generator.ex
index 93b19484f..70413837a 100644
--- a/lib/pleroma/docs/generator.ex
+++ b/lib/pleroma/docs/generator.ex
@@ -1,138 +1,151 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Docs.Generator do
@callback process(keyword()) :: {:ok, String.t()}
@spec process(module(), keyword()) :: {:ok, String.t()}
def process(implementation, descriptions) do
implementation.process(descriptions)
end
@spec list_behaviour_implementations(behaviour :: module()) :: [module()]
def list_behaviour_implementations(behaviour) do
- :code.all_loaded()
- |> Enum.filter(fn {module, _} ->
+ # :code.all_loaded() no longer works on Elixir 1.19 and newer since modules are lazily loaded.
+ # We can get a complete list of modules by interating over Application.loaded_applications/0,
+ # but that includes every module which would get loaded below, which is very slow.
+ # Hardcode the Pleroma application instead, which is good enough for now.
+ application_modules =
+ case :application.get_key(:pleroma, :modules) do
+ {:ok, modules} -> modules
+ :undefined -> []
+ end
+
+ # At compile time or in tests some modules will be outside of the Pleroma application.
+ loaded_modules = Enum.map(:code.all_loaded(), fn {module, _} -> module end)
+
+ (application_modules ++ loaded_modules)
+ |> Enum.uniq()
+ |> Enum.filter(fn module ->
+ Code.ensure_loaded(module)
+
# This shouldn't be needed as all modules are expected to have module_info/1,
# but in test environments some transient modules `:elixir_compiler_XX`
# are loaded for some reason (where XX is a random integer).
- Code.ensure_loaded(module)
-
if function_exported?(module, :module_info, 1) do
module.module_info(:attributes)
|> Keyword.get_values(:behaviour)
|> List.flatten()
|> Enum.member?(behaviour)
end
end)
- |> Enum.map(fn {module, _} -> module end)
end
@doc """
Converts:
- atoms to strings with leading `:`
- module names to strings, without leading `Elixir.`
- add humanized labels to `keys` if label is not defined, e.g. `:instance` -> `Instance`
"""
@spec convert_to_strings([map()]) :: [map()]
def convert_to_strings(descriptions) do
Enum.map(descriptions, &format_entity(&1))
end
defp format_entity(entity) do
entity
|> format_key()
|> Map.put(:group, atom_to_string(entity[:group]))
|> format_children()
end
defp format_key(%{key: key} = entity) do
entity
|> Map.put(:key, atom_to_string(key))
|> Map.put(:label, entity[:label] || humanize(key))
end
defp format_key(%{group: group} = entity) do
Map.put(entity, :label, entity[:label] || humanize(group))
end
defp format_key(entity), do: entity
defp format_children(%{children: children} = entity) do
Map.put(entity, :children, Enum.map(children, &format_child(&1)))
end
defp format_children(entity), do: entity
defp format_child(%{suggestions: suggestions} = entity) do
entity
|> Map.put(:suggestions, format_suggestions(suggestions))
|> format_key()
|> format_group()
|> format_children()
end
defp format_child(entity) do
entity
|> format_key()
|> format_group()
|> format_children()
end
defp format_group(%{group: group} = entity) do
Map.put(entity, :group, format_suggestion(group))
end
defp format_group(entity), do: entity
defp atom_to_string(entity) when is_binary(entity), do: entity
defp atom_to_string(entity) when is_atom(entity), do: inspect(entity)
defp humanize(entity) do
string = inspect(entity)
if String.starts_with?(string, ":"),
do: Phoenix.Naming.humanize(entity),
else: string
end
defp format_suggestions({:list_behaviour_implementations, behaviour}) do
behaviour
|> list_behaviour_implementations()
|> format_suggestions()
end
defp format_suggestions([]), do: []
defp format_suggestions([suggestion | tail]) do
[format_suggestion(suggestion) | format_suggestions(tail)]
end
defp format_suggestion(entity) when is_atom(entity) do
atom_to_string(entity)
end
defp format_suggestion([head | tail] = entity) when is_list(entity) do
[format_suggestion(head) | format_suggestions(tail)]
end
defp format_suggestion(entity) when is_tuple(entity) do
format_suggestions(Tuple.to_list(entity)) |> List.to_tuple()
end
defp format_suggestion(entity), do: entity
end
defimpl Jason.Encoder, for: Tuple do
def encode(tuple, opts), do: Jason.Encode.list(Tuple.to_list(tuple), opts)
end
defimpl Jason.Encoder, for: [Regex, Function] do
def encode(term, opts), do: Jason.Encode.string(inspect(term), opts)
end
defimpl String.Chars, for: Regex do
def to_string(term), do: inspect(term)
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Oct 30, 1:11 PM (14 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1800157
Default Alt Text
(5 KB)
Attached To
Mode
rPUBE pleroma-upstream
Attached
Detach File
Event Timeline