Ancora.TagScanner (ancora v1.0.0-rc.1)

Copy Markdown View Source

Discovers @tag spec:, @moduletag spec:, and @describetag spec: values in ExUnit files.

Literal ids are recorded. A non-literal value is never guessed: it becomes a dynamic entry instead. fold_to_subjects/1 lifts requirement ids to their parent subject ids for the detector.

Summary

Functions

Folds requirement-id tags up to parent subject ids.

Scans each directory in paths for *_test.exs files and aggregates results.

Scans a single test file and returns its @tag spec: occurrences.

Types

dynamic_entry()

@type dynamic_entry() :: %{
  file: String.t(),
  line: non_neg_integer(),
  test_name: String.t() | nil
}

parse_error()

@type parse_error() :: %{file: String.t(), reason: term()}

tag_entry()

@type tag_entry() :: %{
  id: String.t(),
  file: String.t(),
  line: non_neg_integer(),
  test_line: non_neg_integer(),
  test_name: String.t() | nil
}

Functions

fold_to_subjects(tags)

@spec fold_to_subjects([tag_entry()]) :: [tag_entry()]
@spec fold_to_subjects(%{required(String.t()) => [tag_entry()]}) :: %{
  required(String.t()) => [tag_entry()]
}

Folds requirement-id tags up to parent subject ids.

A tag ancora.parsing.tag_discovery also attributes its file to ancora.parsing. The detector uses the folded entries to attribute test files to subjects. Non-literal tags never enter this list.

scan(paths, opts \\ [])

@spec scan(
  [String.t()],
  keyword()
) ::
  {:ok, %{required(String.t()) => [tag_entry()]}, [parse_error()],
   [dynamic_entry()]}

Scans each directory in paths for *_test.exs files and aggregates results.

Returns {:ok, tag_map, parse_errors, dynamic_entries} where:

  • tag_map is %{requirement_id => [tag_entry]}
  • parse_errors is a list of %{file, reason} for unparseable files
  • dynamic_entries is a list of annotations whose value could not be resolved to a literal

scan_file(path, opts \\ [])

@spec scan_file(
  String.t(),
  keyword()
) ::
  {:ok, [tag_entry()]}
  | {:ok, [tag_entry()], [dynamic_entry()]}
  | {:error, term()}

Scans a single test file and returns its @tag spec: occurrences.

Returns {:ok, tags} on a parseable file, or {:ok, tags, dynamic} when :include_dynamic is true. Returns {:error, reason} when the file cannot be parsed as Elixir.