From 3da72f9e6ac72ad5470c701e71d7446f398ce596 Mon Sep 17 00:00:00 2001 From: rustra Date: Mon, 2 Mar 2020 23:42:15 +0100 Subject: [PATCH] Specs improvements and fixes --- lib/rdf/blank_node/increment.ex | 1 - lib/rdf/dataset.ex | 22 +++++++++++----------- lib/rdf/graph.ex | 18 +++++++++--------- lib/rdf/iri.ex | 24 ++++++++++++------------ lib/rdf/list.ex | 2 +- lib/rdf/literal.ex | 7 ++++--- lib/rdf/namespace.ex | 4 ++-- lib/rdf/prefix_map.ex | 28 ++++++++++++++++------------ lib/rdf/vocabulary_namespace.ex | 3 +-- 9 files changed, 56 insertions(+), 53 deletions(-) diff --git a/lib/rdf/blank_node/increment.ex b/lib/rdf/blank_node/increment.ex index d5e2c2f..b252229 100644 --- a/lib/rdf/blank_node/increment.ex +++ b/lib/rdf/blank_node/increment.ex @@ -31,7 +31,6 @@ defmodule RDF.BlankNode.Increment do end @impl BlankNode.Generator.Algorithm - # @spec generate(map) :: {RDF.BlankNode.t, map} def generate(%{counter: counter} = state) do {bnode(counter, state), %{state | counter: counter + 1}} end diff --git a/lib/rdf/dataset.ex b/lib/rdf/dataset.ex index a35d66f..6ece96b 100644 --- a/lib/rdf/dataset.ex +++ b/lib/rdf/dataset.ex @@ -18,16 +18,16 @@ defmodule RDF.Dataset do alias RDF.{Description, Graph, IRI, Statement} import RDF.Statement - @type graphs_key :: IRI.t | nil + @type graph_name :: IRI.t | nil @type t :: %__MODULE__{ - name: IRI.t | nil, - graphs: %{graphs_key => Graph.t} + name: graph_name, + graphs: %{graph_name => Graph.t} } - @type t_param :: Graph.t_param | t + @type input :: Graph.input | t - @type update_graph_fun :: (Graph.t -> {Graph.t, t_param} | :pop) + @type update_graph_fun :: (Graph.t -> {Graph.t, input} | :pop) defstruct name: nil, graphs: %{} @@ -53,7 +53,7 @@ defmodule RDF.Dataset do RDF.Graph.new(name: EX.GraphName) """ - @spec new(t_param | [t_param] | keyword) :: t + @spec new(input | [input] | keyword) :: t def new(data_or_options) def new(data_or_options) @@ -83,7 +83,7 @@ defmodule RDF.Dataset do - `name`: the name of the dataset to be created """ - @spec new(t_param | [t_param], keyword) :: t + @spec new(input | [input], keyword) :: t def new(data, options) def new(%RDF.Dataset{} = graph, options) do @@ -104,7 +104,7 @@ defmodule RDF.Dataset do destination graph to which the statements are added, ignoring the graph context of given quads or the name of given graphs. """ - @spec add(t, t_param | [t_param], boolean | nil) :: t + @spec add(t, input | [input], boolean | nil) :: t def add(dataset, statements, graph_context \\ false) def add(dataset, statements, graph_context) when is_list(statements) do @@ -186,7 +186,7 @@ defmodule RDF.Dataset do ...> RDF.Dataset.put([{EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}]) RDF.Dataset.new([{EX.S1, EX.P1, EX.O1}, {EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}]) """ - @spec put(t, t_param | [t_param], Statement.coercible_graph_name | boolean | nil) :: t + @spec put(t, input | [input], Statement.coercible_graph_name | boolean | nil) :: t def put(dataset, statements, graph_context \\ false) def put(%RDF.Dataset{} = dataset, {subject, predicate, objects}, false), @@ -307,7 +307,7 @@ defmodule RDF.Dataset do are deleted. If you want to delete only datasets with matching names, you can use `RDF.Data.delete/2`. """ - @spec delete(t, t_param | [t_param], Statement.coercible_graph_name | boolean | nil) :: t + @spec delete(t, input | [input], Statement.coercible_graph_name | boolean | nil) :: t def delete(dataset, statements, graph_context \\ false) def delete(%RDF.Dataset{} = dataset, statements, graph_context) when is_list(statements) do @@ -486,7 +486,7 @@ defmodule RDF.Dataset do {RDF.Graph.new({EX.S, EX.P, EX.O}, name: EX.Graph), RDF.Dataset.new({EX.S, EX.P, EX.NEW, EX.Graph})} """ @impl Access - @spec get_and_update(t, Statement.graph_name | nil, update_graph_fun) :: {Graph.t, t_param} + @spec get_and_update(t, Statement.graph_name | nil, update_graph_fun) :: {Graph.t, input} def get_and_update(%RDF.Dataset{} = dataset, graph_name, fun) do with graph_context = coerce_graph_name(graph_name) do case fun.(get(dataset, graph_context)) do diff --git a/lib/rdf/graph.ex b/lib/rdf/graph.ex index 1ea0696..35c8244 100644 --- a/lib/rdf/graph.ex +++ b/lib/rdf/graph.ex @@ -16,7 +16,7 @@ defmodule RDF.Graph do import RDF.Statement alias RDF.{Description, IRI, PrefixMap, Statement} - @type graph_description :: %{IRI.t => Description.t} + @type graph_description :: %{Statement.subject => Description.t} @type t :: %__MODULE__{ name: IRI.t | nil, @@ -25,11 +25,11 @@ defmodule RDF.Graph do base_iri: IRI.t | nil } - @type t_param :: Statement.t | Description.t | t + @type input :: Statement.t | Description.t | t @type update_description_fun :: (Description.t -> Description.t) - @type get_and_update_description_fun :: (Description.t -> {Description.t, t_param} | :pop) + @type get_and_update_description_fun :: (Description.t -> {Description.t, input} | :pop) defstruct name: nil, descriptions: %{}, prefixes: nil, base_iri: nil @@ -55,7 +55,7 @@ defmodule RDF.Graph do RDF.Graph.new(name: EX.GraphName) """ - @spec new(t_param | [t_param] | keyword) :: t + @spec new(input | [input] | keyword) :: t def new(data_or_options) def new(data_or_options) @@ -98,7 +98,7 @@ defmodule RDF.Graph do RDF.Graph.new({EX.S, EX.p, EX.O}, name: EX.GraphName, base_iri: EX.base) """ - @spec new(t_param | [t_param], keyword) :: t + @spec new(input | [input], keyword) :: t def new(data, options) def new(%RDF.Graph{} = graph, options) do @@ -165,7 +165,7 @@ defmodule RDF.Graph do prefixes of this graph will be added. In case of conflicting prefix mappings the original prefix from `graph` will be kept. """ - @spec add(t, t_param | [t_param]) :: t + @spec add(t, input | [input]) :: t def add(graph, triples) def add(%RDF.Graph{} = graph, {subject, _, _} = statement), @@ -221,7 +221,7 @@ defmodule RDF.Graph do RDF.Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}]) """ - @spec put(t, t_param | [t_param]) :: t + @spec put(t, input | [input]) :: t def put(graph, statements) def put(%RDF.Graph{} = graph, {subject, _, _} = statement), @@ -331,7 +331,7 @@ defmodule RDF.Graph do use `RDF.Data.delete/2`. """ - @spec delete(t, t_param | [t_param]) :: t + @spec delete(t, input | [input]) :: t def delete(graph, triples) def delete(%RDF.Graph{} = graph, {subject, _, _} = triple), @@ -543,7 +543,7 @@ defmodule RDF.Graph do """ @impl Access @spec get_and_update(t, Statement.coercible_subject, get_and_update_description_fun) :: - {Description.t, t_param} + {Description.t, input} def get_and_update(%RDF.Graph{} = graph, subject, fun) do with subject = coerce_subject(subject) do case fun.(get(graph, subject)) do diff --git a/lib/rdf/iri.ex b/lib/rdf/iri.ex index 49100d6..3d5bd1b 100644 --- a/lib/rdf/iri.ex +++ b/lib/rdf/iri.ex @@ -16,13 +16,13 @@ defmodule RDF.IRI do see """ - alias RDF.{Datatype, Namespace} + alias RDF.Namespace @type t :: %__MODULE__{ value: String.t } - @type t_param :: String.t | Datatype.t | URI.t | t + @type coercible :: String.t | URI.t | module | t @enforce_keys [:value] defstruct [:value] @@ -47,7 +47,7 @@ defmodule RDF.IRI do @doc """ Creates a `RDF.IRI`. """ - @spec new(t_param) :: t + @spec new(coercible) :: t def new(iri) def new(iri) when is_binary(iri), do: %RDF.IRI{value: iri} def new(qname) when is_atom(qname) and qname not in [nil, true, false], @@ -62,7 +62,7 @@ defmodule RDF.IRI do see `valid?/1` """ - @spec new!(t_param) :: t + @spec new!(coercible) :: t def new!(iri) def new!(iri) when is_binary(iri), do: iri |> valid!() |> new() def new!(qname) when is_atom(qname) and qname not in [nil, true, false], @@ -77,7 +77,7 @@ defmodule RDF.IRI do As opposed to `new/1` this also accepts bare `RDF.Vocabulary.Namespace` modules and uses the base IRI from their definition. """ - @spec coerce_base(t_param) :: t + @spec coerce_base(coercible) :: t def coerce_base(base_iri) def coerce_base(module) when is_atom(module) do @@ -103,7 +103,7 @@ defmodule RDF.IRI do iex> RDF.IRI.valid!("not an iri") ** (RDF.IRI.InvalidError) Invalid IRI: "not an iri" """ - @spec valid!(t_param) :: t_param + @spec valid!(coercible) :: coercible def valid!(iri) do if not valid?(iri), do: raise RDF.IRI.InvalidError, "Invalid IRI: #{inspect iri}" iri @@ -122,7 +122,7 @@ defmodule RDF.IRI do iex> RDF.IRI.valid?("not an iri") false """ - @spec valid?(t_param) :: boolean + @spec valid?(coercible) :: boolean def valid?(iri), do: absolute?(iri) # TODO: Provide a more elaborate validation @@ -159,7 +159,7 @@ defmodule RDF.IRI do If the given is not an absolute IRI `nil` is returned. """ - @spec absolute(t_param, t_param) :: t | nil + @spec absolute(coercible, coercible) :: t | nil def absolute(iri, base) do cond do absolute?(iri) -> new(iri) @@ -175,7 +175,7 @@ defmodule RDF.IRI do This function merges two IRIs as per [RFC 3986, section 5.2](https://tools.ietf.org/html/rfc3986#section-5.2). """ - @spec merge(t_param, t_param) :: t + @spec merge(coercible, coercible) :: t def merge(base, rel) do base |> parse() @@ -196,7 +196,7 @@ defmodule RDF.IRI do iex> RDF.IRI.scheme("not an iri") nil """ - @spec scheme(t_param) :: String.t | nil + @spec scheme(coercible) :: String.t | nil def scheme(iri) def scheme(%RDF.IRI{value: value}), do: scheme(value) def scheme(%URI{scheme: scheme}), do: scheme @@ -211,7 +211,7 @@ defmodule RDF.IRI do @doc """ Parses an IRI into its components and returns them as an `URI` struct. """ - @spec parse(t_param) :: URI.t + @spec parse(coercible) :: URI.t def parse(iri) def parse(iri) when is_binary(iri), do: URI.parse(iri) def parse(qname) when is_atom(qname) and qname not in [nil, true, false], @@ -260,7 +260,7 @@ defmodule RDF.IRI do "http://example.com/#Foo" """ - @spec to_string(t | Datatype.t) :: String.t + @spec to_string(t | module) :: String.t def to_string(iri) def to_string(%RDF.IRI{value: value}), diff --git a/lib/rdf/list.ex b/lib/rdf/list.ex index 1ec3a74..408dea8 100644 --- a/lib/rdf/list.ex +++ b/lib/rdf/list.ex @@ -31,7 +31,7 @@ defmodule RDF.List do - does not contain cycles, i.e. `rdf:rest` statements don't refer to preceding list nodes """ - @spec new(IRI.t_param, Graph.t) :: t + @spec new(IRI.coercible, Graph.t) :: t def new(head, graph) def new(head, graph) when is_atom(head) and head not in ~w[true false nil]a, diff --git a/lib/rdf/literal.ex b/lib/rdf/literal.ex index 6341a7e..432498a 100644 --- a/lib/rdf/literal.ex +++ b/lib/rdf/literal.ex @@ -381,13 +381,14 @@ defmodule RDF.Literal do |> String.downcase() |> String.contains?(String.downcase(pattern)) - # _ -> - # raise "Invalid XQuery regex pattern or flags" + _ -> + raise "Invalid XQuery regex pattern or flags" end end @doc false - @spec xpath_pattern(t | String.t, t | String.t) :: {:regex, Regex.t} | {:q | :qi, String.t} + @spec xpath_pattern(t | String.t, t | String.t) :: + {:q | :qi, String.t} | {:regex, Regex.t} | {:error, any} def xpath_pattern(pattern, flags) def xpath_pattern(%RDF.Literal{datatype: @xsd_string} = pattern, flags), diff --git a/lib/rdf/namespace.ex b/lib/rdf/namespace.ex index 24f0bd1..076a1ad 100644 --- a/lib/rdf/namespace.ex +++ b/lib/rdf/namespace.ex @@ -7,7 +7,7 @@ defmodule RDF.Namespace do namespaces for JSON-LD contexts. """ - alias RDF.{Datatype, IRI} + alias RDF.IRI @doc """ Resolves a term to a `RDF.IRI`. @@ -27,7 +27,7 @@ defmodule RDF.Namespace do delegates to remaining part of the term to `__resolve_term__/1` of this determined namespace. """ - @spec resolve_term(IRI.t | Datatype.t) :: IRI.t + @spec resolve_term(IRI.t | module) :: IRI.t def resolve_term(expr) def resolve_term(%IRI{} = iri), do: iri diff --git a/lib/rdf/prefix_map.ex b/lib/rdf/prefix_map.ex index 67014ae..8709d9d 100644 --- a/lib/rdf/prefix_map.ex +++ b/lib/rdf/prefix_map.ex @@ -7,12 +7,16 @@ defmodule RDF.PrefixMap do alias RDF.IRI - @type prefix :: atom | String.t - @type namespace :: atom | String.t | IRI.t + @type prefix :: atom + @type namespace :: IRI.t + + @type coercible_prefix :: atom | String.t + @type coercible_namespace :: atom | String.t | IRI.t @type prefix_map :: %{prefix => namespace} - @type conflict_resolver :: (prefix, namespace, namespace -> namespace) + @type conflict_resolver :: + (coercible_prefix, coercible_namespace, coercible_namespace -> coercible_namespace) @type t :: %__MODULE__{ map: prefix_map @@ -63,7 +67,7 @@ defmodule RDF.PrefixMap do Unless a mapping of the given prefix to a different namespace already exists, an ok tuple is returned, other an error tuple. """ - @spec add(t, prefix, namespace) :: {:ok, t} | {:error, String.t} + @spec add(t, coercible_prefix, coercible_namespace) :: {:ok, t} | {:error, String.t} def add(prefix_map, prefix, namespace) def add(%__MODULE__{map: map}, prefix, %IRI{} = namespace) when is_atom(prefix) do @@ -83,7 +87,7 @@ defmodule RDF.PrefixMap do @doc """ Adds a prefix mapping to the given `RDF.PrefixMap` and raises an exception in error cases. """ - @spec add!(t, prefix, namespace) :: t + @spec add!(t, coercible_prefix, coercible_namespace) :: t def add!(prefix_map, prefix, namespace) do with {:ok, new_prefix_map} <- add(prefix_map, prefix, namespace) do new_prefix_map @@ -213,7 +217,7 @@ defmodule RDF.PrefixMap do @doc """ Deletes a prefix mapping from the given `RDF.PrefixMap`. """ - @spec delete(t, prefix) :: t + @spec delete(t, coercible_prefix) :: t def delete(prefix_map, prefix) def delete(%__MODULE__{map: map}, prefix) when is_atom(prefix) do @@ -229,7 +233,7 @@ defmodule RDF.PrefixMap do If `prefixes` contains prefixes that are not in `prefix_map`, they're simply ignored. """ - @spec drop(t, [prefix]) :: t + @spec drop(t, [coercible_prefix]) :: t def drop(prefix_map, prefixes) def drop(%__MODULE__{map: map}, prefixes) do @@ -250,7 +254,7 @@ defmodule RDF.PrefixMap do Returns `nil`, when the given `prefix` is not present in `prefix_map`. """ - @spec namespace(t, prefix) :: namespace | nil + @spec namespace(t, coercible_prefix) :: namespace | nil def namespace(prefix_map, prefix) def namespace(%__MODULE__{map: map}, prefix) when is_atom(prefix) do @@ -266,7 +270,7 @@ defmodule RDF.PrefixMap do Returns `nil`, when the given `namespace` is not present in `prefix_map`. """ - @spec prefix(t, namespace) :: prefix | nil + @spec prefix(t, coercible_namespace) :: coercible_prefix | nil def prefix(prefix_map, namespace) def prefix(%__MODULE__{map: map}, %IRI{} = namespace) do @@ -280,7 +284,7 @@ defmodule RDF.PrefixMap do @doc """ Returns whether the given prefix exists in the given `RDF.PrefixMap`. """ - @spec has_prefix?(t, prefix) :: boolean + @spec has_prefix?(t, coercible_prefix) :: boolean def has_prefix?(prefix_map, prefix) def has_prefix?(%__MODULE__{map: map}, prefix) when is_atom(prefix) do @@ -294,7 +298,7 @@ defmodule RDF.PrefixMap do @doc """ Returns all prefixes from the given `RDF.PrefixMap`. """ - @spec prefixes(t) :: [prefix] + @spec prefixes(t) :: [coercible_prefix] def prefixes(%__MODULE__{map: map}) do Map.keys(map) end @@ -302,7 +306,7 @@ defmodule RDF.PrefixMap do @doc """ Returns all namespaces from the given `RDF.PrefixMap`. """ - @spec namespaces(t) :: [namespace] + @spec namespaces(t) :: [coercible_namespace] def namespaces(%__MODULE__{map: map}) do Map.values(map) end diff --git a/lib/rdf/vocabulary_namespace.ex b/lib/rdf/vocabulary_namespace.ex index 8ff5464..b830b90 100644 --- a/lib/rdf/vocabulary_namespace.ex +++ b/lib/rdf/vocabulary_namespace.ex @@ -9,7 +9,6 @@ defmodule RDF.Vocabulary.Namespace do the `RDF.NS` module. """ - alias RDF.Datatype alias RDF.Utils.ResourceClassifier @vocabs_dir "priv/vocabs" @@ -576,7 +575,7 @@ defmodule RDF.Vocabulary.Namespace do do: RDF.iri(base_iri <> term) @doc false - @spec vocabulary_namespace?(Datatype.t) :: boolean + @spec vocabulary_namespace?(module) :: boolean def vocabulary_namespace?(name) do Code.ensure_compiled?(name) && function_exported?(name, :__base_iri__, 0) end