• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

exercism / elixir-analyzer / 81bb2bd44c91598e28b337a76394d2632f36db5b

29 Sep 2025 12:19AM UTC coverage: 98.524%. Remained the same
81bb2bd44c91598e28b337a76394d2632f36db5b

push

github

web-flow
Add analyzer for gotta-snatch-em-all (#451)

* Add analyzer for gotta-snatch-em-all

* Fix space alignment & formatting

* Add tests for gotta snatch em all analyzer

* Fix wording & spelling mistakes

Co-authored-by: Jie <jie.gillet@gmail.com>

---------

Co-authored-by: Jie <jie.gillet@gmail.com>

868 of 881 relevant lines covered (98.52%)

16232.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.45
/lib/elixir_analyzer/exercise_test/check_source.ex
1
defmodule ElixirAnalyzer.ExerciseTest.CheckSource do
2
  @moduledoc """
3
  Defines a `check_source` macro that allows checking the source code
4
  """
5

6
  alias ElixirAnalyzer.Comment
7

8
  @doc false
9
  defmacro __using__(_opts) do
10
    quote do
11
      import unquote(__MODULE__)
12

13
      @check_source_tests []
14
    end
15
  end
16

17
  @doc """
18
  Defines a macro which runs a boolean function on the source code.
19

20
  This macro then collates the block into a map structure resembling:
21
  test_data = %{
22
    description: description,
23
    type: :actionable,
24
    comment: "message",
25
    suppress_if: [{"name of other test", :fail}]
26
  }
27
  and an AST for the function
28
  """
29
  defmacro check_source(description, do: block) do
30
    :ok = validate_check_block(block)
42✔
31

32
    test_data =
41✔
33
      block
34
      |> walk_check_source_block()
35
      |> Map.put(:description, description)
36
      |> Map.put_new(:type, :informative)
37

38
    check = test_data.check
39✔
39

40
    test_data =
39✔
41
      test_data
42
      |> Map.delete(:check)
43
      # made into a key-val list for better quoting
44
      |> Map.to_list()
45

46
    unless Keyword.has_key?(test_data, :comment) do
39✔
47
      raise "Comment must be defined for each check_source test"
1✔
48
    end
49

50
    quote do
51
      @check_source_tests [
52
        {unquote(test_data), unquote(Macro.escape(check))} | @check_source_tests
53
      ]
54
    end
55
  end
56

57
  @supported_expressions [:comment, :type, :suppress_if, :check]
58
  defp validate_check_block({:__block__, _, args}) do
59
    Enum.each(args, fn {name, _, _} ->
42✔
60
      if name not in @supported_expressions do
121✔
61
        raise """
1✔
62
        Unsupported expression `#{name}`.
1✔
63
        The macro `check_source` supports expressions: #{Enum.join(@supported_expressions, ", ")}.
64
        """
65
      end
66
    end)
67
  end
68

69
  defp walk_check_source_block(block, test_data \\ %{}) do
70
    {_, test_data} = Macro.prewalk(block, test_data, &do_walk_check_source_block/2)
41✔
71
    test_data
39✔
72
  end
73

74
  defp do_walk_check_source_block({:comment, _, [comment]} = node, test_data) do
38✔
75
    {node, Map.put(test_data, :comment, comment)}
76
  end
77

78
  defp do_walk_check_source_block({:type, _, [type]} = node, test_data) do
79
    if not Comment.supported_type?(type) do
38✔
80
      raise """
1✔
81
      Unsupported type `#{type}`.
1✔
82
      The macro `check_source` supports the following types: #{Enum.join(Comment.supported_types(), ", ")}.
83
      """
84
    end
85

86
    {node, Map.put(test_data, :type, type)}
87
  end
88

89
  defp do_walk_check_source_block({:suppress_if, _, args} = node, test_data) do
90
    case args do
2✔
91
      [name, condition] when condition in [:pass, :fail] ->
92
        test_data =
1✔
93
          Map.update(test_data, :suppress_if, [{name, condition}], &[{name, condition} | &1])
×
94

95
        {node, test_data}
96

97
      _ ->
98
        raise """
1✔
99
        Invalid :suppress_if arguments. Arguments must have the form
100
          suppress_if "some check name", (:pass | :fail)
101
        """
102
    end
103
  end
104

105
  defp do_walk_check_source_block({:check, _, [source, [do: function]]} = node, test_data) do
106
    function = {:fn, [], [{:->, [], [[source], function]}]}
39✔
107

108
    {node, Map.put(test_data, :check, function)}
109
  end
110

111
  defp do_walk_check_source_block(node, test_data) do
3,733✔
112
    {node, test_data}
113
  end
114
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc