Packages

spark

2.3.14
2.7.2 2.7.1 2.7.0 2.6.1 2.6.0 2.5.0 2.4.1 2.4.0 2.3.14 2.3.13 2.3.12 2.3.11 2.3.10 2.3.9 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.69 2.2.68 2.2.67 2.2.66 2.2.65 2.2.64 2.2.63 2.2.62 2.2.61 2.2.60 2.2.59 2.2.58 2.2.57 2.2.56 2.2.55 2.2.54 2.2.53 2.2.52 2.2.51 2.2.50 2.2.49 2.2.48 2.2.47 2.2.46 2.2.45 2.2.44 2.2.43 2.2.42 2.2.41 2.2.40 2.2.39 2.2.38 2.2.37 2.2.36 2.2.35 2.2.34 2.2.33 2.2.32 2.2.31 2.2.30 2.2.29 2.2.28 2.2.27 2.2.26 2.2.25 2.2.24 2.2.23 2.2.22 2.2.21 2.2.20 2.2.19 2.2.18 2.2.17 2.2.16 2.2.15 2.2.14 2.2.13 2.2.12 2.2.11 2.2.10 2.2.9 2.2.8 2.2.7 2.2.6 2.2.5 2.2.4 2.2.3 2.2.2 2.2.1 2.2.0 2.1.24 2.1.23 2.1.22 2.1.21 2.1.20 2.1.19 2.1.18 2.1.17 2.1.16 2.1.15 2.1.14 2.1.13 2.1.12 2.1.11 2.1.10 2.1.9 2.1.8 2.1.7 2.1.6 2.1.5 2.1.4 2.1.3 2.1.2 2.1.1 2.1.0 2.0.1 2.0.0 1.1.55 1.1.54 1.1.53 1.1.52 1.1.51 1.1.50 1.1.49 1.1.48 1.1.47 1.1.46 1.1.45 1.1.44 1.1.43 1.1.42 1.1.41 1.1.40 1.1.39 1.1.38 1.1.37 1.1.36 1.1.35 1.1.34 1.1.32 1.1.31 1.1.30 1.1.29 1.1.28 1.1.27 1.1.26 1.1.25 1.1.24 1.1.22 1.1.21 1.1.20 1.1.19 1.1.18 1.1.17 1.1.16 1.1.15 1.1.14 retired 1.1.13 1.1.12 1.1.11 1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.9 1.0.8 1.0.7 1.0.6 1.0.5 1.0.4 1.0.3 1.0.2 1.0.1 1.0.0 0.4.12 0.4.11 0.4.10 0.4.9 0.4.8 0.4.7 0.4.6 0.4.5 0.4.4 0.4.3 0.4.2 0.4.1 0.3.12 0.3.11 0.3.10 0.3.9 0.3.8 0.3.7 0.3.6 0.3.5 0.3.4 0.3.3 0.3.2 0.3.1 0.3.0 0.2.18 0.2.17 0.2.16 0.2.15 0.2.14 0.2.13 0.2.12 0.2.11 0.2.10 0.2.9 0.2.8 0.2.7 0.2.6 0.2.5 0.2.4 0.2.3 0.2.2 0.2.1 0.2.0 0.1.29 0.1.28 0.1.27 0.1.26 0.1.25 0.1.24 0.1.23 0.1.22 0.1.21 0.1.20 0.1.19 0.1.18 0.1.17 0.1.16 0.1.15 0.1.14 0.1.13 0.1.12 0.1.11 0.1.10 0.1.9 0.1.8 0.1.7 0.1.6 0.1.5 0.1.4 0.1.3 0.1.2 0.1.1 0.1.0

Generic tooling for building DSLs

Current section

Files

Jump to
spark lib spark dsl verifiers verify_entity_uniqueness.ex
Raw

lib/spark/dsl/verifiers/verify_entity_uniqueness.ex

# SPDX-FileCopyrightText: 2022 spark contributors <https://github.com/ash-project/spark/graphs.contributors>
#
# SPDX-License-Identifier: MIT
defmodule Spark.Dsl.Verifiers.VerifyEntityUniqueness do
@moduledoc """
Verifies that each entity that has an identifier is unique at each path.
"""
use Spark.Dsl.Verifier
alias Spark.Dsl.Verifier
def verify(dsl_state) do
module = Verifier.get_persisted(dsl_state, :module)
dsl_state
|> Verifier.get_persisted(:extensions)
|> Enum.each(fn extension ->
Enum.each(extension.sections(), fn section ->
verify_entity_uniqueness(module, section, dsl_state)
end)
end)
:ok
end
defp verify_entity_uniqueness(module, section, dsl_state, path \\ []) do
section_path = path ++ [section.name]
section.entities
|> Enum.each(fn entity ->
do_verify_entity_uniqueness(module, entity, section_path, dsl_state)
end)
Enum.each(section.sections, fn section ->
verify_entity_uniqueness(module, section, dsl_state, section_path)
end)
section.entities
|> Enum.each(fn entity ->
entities_to_check = Verifier.get_entities(dsl_state, section_path)
entity.entities
|> Enum.flat_map(fn {key, nested_entities} ->
Enum.map(nested_entities, &{key, &1})
end)
|> Enum.each(fn {key, nested_entity} ->
verify_nested_entity_uniqueness(
module,
nested_entity,
section_path,
entities_to_check,
[key]
)
end)
end)
end
defp verify_nested_entity_uniqueness(
module,
nested_entity,
section_path,
entities_to_check,
nested_entity_path
) do
unique_entities_or_error(
entities_to_check,
nested_entity.identifier,
module,
section_path ++ nested_entity_path
)
entities_to_check
|> Enum.each(fn entity_to_check ->
nested_entity.entities
|> Enum.flat_map(fn {key, nested_entities} ->
Enum.map(nested_entities, &{key, &1})
end)
|> Enum.filter(fn {_, nested_entity} ->
nested_entity.identifier
end)
|> Enum.each(fn {key, nested_entity} ->
nested_entities_to_check =
entity_to_check
|> Map.get(key)
|> List.wrap()
verify_nested_entity_uniqueness(
module,
nested_entity,
section_path,
nested_entities_to_check,
nested_entity_path ++ [key]
)
end)
end)
end
defp do_verify_entity_uniqueness(module, entity, section_path, dsl_state) do
dsl_state
|> Verifier.get_entities(section_path)
|> Enum.filter(&(&1.__struct__ == entity.target))
|> unique_entities_or_error(entity.identifier, module, section_path)
end
defp unique_entities_or_error(_, nil, _, _), do: :ok
defp unique_entities_or_error(entities_to_check, identifier, module, path) do
entities_to_check
|> Enum.group_by(&{get_identifier(&1, identifier), &1.__struct__})
|> Enum.find(&match?({_, [_first, _second | _]}, &1))
|> case do
nil ->
:ok
{{identifier, target}, [duplicate_entity | _rest]} ->
location = Spark.Dsl.Entity.anno(duplicate_entity)
raise Spark.Error.DslError,
module: module,
path: path ++ [identifier],
message: """
Got duplicate #{inspect(target)}: #{identifier}
""",
location: location
end
end
defp get_identifier(record, {:auto, _}), do: record.__identifier__
defp get_identifier(record, identifier), do: Map.get(record, identifier)
end