From 56048f88dff0db934ae52ee631382fe348502f1c Mon Sep 17 00:00:00 2001 From: Kah Goh Date: Tue, 15 Jul 2025 22:20:08 +0800 Subject: [PATCH 1/2] Add analyzer for gotta-snatch-em-all --- config/config.exs | 3 + lib/elixir_analyzer/constants.ex | 15 ++ .../test_suite/gotta-snatch-em-all.ex | 139 ++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 lib/elixir_analyzer/test_suite/gotta-snatch-em-all.ex diff --git a/config/config.exs b/config/config.exs index 3cbc3c08..f2dc74cc 100644 --- a/config/config.exs +++ b/config/config.exs @@ -63,6 +63,9 @@ config :elixir_analyzer, "german-sysadmin" => %{ analyzer_module: ElixirAnalyzer.TestSuite.GermanSysadmin }, + "gotta-snatch-em-all" => %{ + analyzer_module: ElixirAnalyzer.TestSuite.GottaSnatchEmAll + }, "high-school-sweetheart" => %{ analyzer_module: ElixirAnalyzer.TestSuite.HighSchoolSweetheart }, diff --git a/lib/elixir_analyzer/constants.ex b/lib/elixir_analyzer/constants.ex index 19247b35..3141c63f 100644 --- a/lib/elixir_analyzer/constants.ex +++ b/lib/elixir_analyzer/constants.ex @@ -100,6 +100,21 @@ defmodule ElixirAnalyzer.Constants do german_sysadmin_no_string: "elixir.german-sysadmin.no_string", german_sysadmin_use_case: "elixir.german-sysadmin.use_case", + # Gotta Snatch Em All Comments + gotta_snatch_em_all_add_card_use_mapset_member_and_put: "elixir.gotta-snatch-em-all.add_card_use_mapset_member_and_put", + gotta_snatch_em_all_trade_card_use_mapset_member_put_and_delete: "elixir.gotta-snatch-em-all.trade_card_use_mapset_member_put_and_delete", + gotta_snatch_em_all_remove_duplicates_use_mapset_new: "elixir.gotta-snatch-em-all.remove_duplicates_use_mapset_new", + gotta_snatch_em_all_remove_duplicates_use_enum_sort: "elixir.gotta-snatch-em-all.remove_duplicates_use_enum_sort", + gotta_snatch_em_all_remove_duplicates_do_not_use_enum_uniq: "elixir.gotta-snatch-em-all.remove_duplicates_do_not_use_enum_uniq", + gotta_snatch_em_all_extra_cards_use_mapset_difference_and_size: "elixir.gotta-snatch-em-all.extra_cards_use_mapset_difference_and_size", + gotta_snatch_em_all_boring_cards_use_mapset_intersection: "elixir.gotta-snatch-em-all.boring_cards_use_mapset_intersection", + gotta_snatch_em_all_boring_cards_use_enum_sort: "elixir.gotta-snatch-em-all.boring_cards_use_enum_sort", + gotta_snatch_em_all_boring_cards_use_enum_reduce: "elixir.gotta-snatch-em-all.boring_cards_use_enum_reduce", + gotta_snatch_em_all_total_cards_use_mapset_union_and_size: "elixir.gotta-snatch-em-all.total_cards_use_mapset_union_and_size", + gotta_snatch_em_all_total_cards_use_enum_reduce: "elixir.gotta-snatch-em-all.total_cards_use_enum_reduce", + gotta_snatch_em_all_split_shiny_cards_use_enum_sort: "elixir.gotta-snatch-em-all.shiny_cards_use_enum_sort", + gotta_snatch_em_all_split_shiny_cards_use_string_starts_with: "elixir.gotta-snatch-em-all.shiny_cards_use_string_starts_with", + # Guessing Game Comments guessing_game_use_default_argument: "elixir.guessing-game.use_default_argument", guessing_game_use_multiple_clause_functions: diff --git a/lib/elixir_analyzer/test_suite/gotta-snatch-em-all.ex b/lib/elixir_analyzer/test_suite/gotta-snatch-em-all.ex new file mode 100644 index 00000000..ff45e6ce --- /dev/null +++ b/lib/elixir_analyzer/test_suite/gotta-snatch-em-all.ex @@ -0,0 +1,139 @@ +defmodule ElixirAnalyzer.TestSuite.GottaSnatchEmAll do + @moduledoc """ + This is an exercise analyzer extension module for the concept exercise Gotta Snatch Em All + """ + use ElixirAnalyzer.ExerciseTest + alias ElixirAnalyzer.Constants + + assert_call "add_call uses MapSet.number?" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :add_card + called_fn module: MapSet, name: :member? + comment Constants.gotta_snatch_em_all_add_card_use_mapset_member_and_put() + end + + assert_call "add_call uses MapSet.put" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :add_card + called_fn module: MapSet, name: :put + comment Constants.gotta_snatch_em_all_add_card_use_mapset_member_and_put() + suppress_if "add_call uses MapSet.number?", :fail + end + + assert_call "trade_card uses MapSet.member?" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :trade_card + called_fn module: MapSet, name: :member? + comment Constants.gotta_snatch_em_all_trade_card_use_mapset_member_put_and_delete() + end + + assert_call "trade_card uses MapSet.put" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :trade_card + called_fn module: MapSet, name: :put + comment Constants.gotta_snatch_em_all_trade_card_use_mapset_member_put_and_delete() + suppress_if "trade_card uses MapSet.member?", :fail + end + + assert_call "trade_card uses MapSet.delete" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :trade_card + called_fn module: MapSet, name: :delete + comment Constants.gotta_snatch_em_all_trade_card_use_mapset_member_put_and_delete() + suppress_if "trade_card uses MapSet.member?", :fail + suppress_if "trade_card uses MapSet.put", :fail + end + + assert_call "remove_duplicates uses MapSet.new" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :remove_duplicates + called_fn module: MapSet, name: :new + comment Constants.gotta_snatch_em_all_remove_duplicates_use_mapset_new() + end + + assert_call "remove_duplicates uses Enum.sort" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :remove_duplicates + called_fn module: Enum, name: :sort + comment Constants.gotta_snatch_em_all_remove_duplicates_use_enum_sort() + end + + assert_no_call "remove_duplicates does not use Enum.uniq" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :remove_duplicates + called_fn module: Enum, name: :uniq + comment Constants.gotta_snatch_em_all_remove_duplicates_do_not_use_enum_uniq() + end + + assert_call "extra_cards uses MapSet.difference" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :extra_cards + called_fn module: MapSet, name: :difference + comment Constants.gotta_snatch_em_all_extra_cards_use_mapset_difference_and_size() + end + + assert_call "extra_cards uses MapSet.size" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :extra_cards + called_fn module: MapSet, name: :size + comment Constants.gotta_snatch_em_all_extra_cards_use_mapset_difference_and_size() + suppress_if "extra_cards uses MapSet.difference", :fail + end + + assert_call "boring_cards uses MapSet.intersection" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :boring_cards + called_fn module: MapSet, name: :intersection + comment Constants.gotta_snatch_em_all_boring_cards_use_mapset_intersection() + end + + assert_call "boring_cards uses Enum.sort" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :boring_cards + called_fn module: Enum, name: :sort + comment Constants.gotta_snatch_em_all_boring_cards_use_enum_sort() + end + + assert_call "boring_cards uses Enum.reduce" do + type :actionable + calling_fn module: GottaSnatchEmAll, name: :boring_cards + called_fn module: Enum, name: :reduce + comment Constants.gotta_snatch_em_all_boring_cards_use_enum_reduce() + end + + assert_call "total_cards uses MapSet.union" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :total_cards + called_fn module: MapSet, name: :union + comment Constants.gotta_snatch_em_all_total_cards_use_mapset_union_and_size() + end + + assert_call "total_cards uses MapSet.size" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :total_cards + called_fn module: MapSet, name: :size + comment Constants.gotta_snatch_em_all_total_cards_use_mapset_union_and_size() + suppress_if "total_cards uses MapSet.union", :fail + end + + assert_call "total_cards uses Enum.reduce" do + type :actionable + calling_fn module: GottaSnatchEmAll, name: :total_cards + called_fn module: Enum, name: :reduce + comment Constants.gotta_snatch_em_all_total_cards_use_enum_reduce() + end + + assert_call "split_shiny_cards uses Enum.sort" do + type :essential + calling_fn module: GottaSnatchEmAll, name: :split_shiny_cards + called_fn module: Enum, name: :sort + comment Constants.gotta_snatch_em_all_split_shiny_cards_use_enum_sort() + end + + assert_call "split_shiny_cards uses String.starts_with" do + type :actionable + calling_fn module: GottaSnatchEmAll, name: :split_shiny_cards + called_fn module: String, name: :starts_with? + comment Constants.gotta_snatch_em_all_split_shiny_cards_use_string_starts_with() + end +end From 726029679b9e8c86c2d4576717c7d4b8602f4420 Mon Sep 17 00:00:00 2001 From: Kah Goh Date: Tue, 15 Jul 2025 22:29:38 +0800 Subject: [PATCH 2/2] Fix space alignment & formatting --- lib/elixir_analyzer/constants.ex | 39 ++++++++++++------- .../test_suite/gotta-snatch-em-all.ex | 2 +- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/lib/elixir_analyzer/constants.ex b/lib/elixir_analyzer/constants.ex index 3141c63f..6a7b7c30 100644 --- a/lib/elixir_analyzer/constants.ex +++ b/lib/elixir_analyzer/constants.ex @@ -101,19 +101,32 @@ defmodule ElixirAnalyzer.Constants do german_sysadmin_use_case: "elixir.german-sysadmin.use_case", # Gotta Snatch Em All Comments - gotta_snatch_em_all_add_card_use_mapset_member_and_put: "elixir.gotta-snatch-em-all.add_card_use_mapset_member_and_put", - gotta_snatch_em_all_trade_card_use_mapset_member_put_and_delete: "elixir.gotta-snatch-em-all.trade_card_use_mapset_member_put_and_delete", - gotta_snatch_em_all_remove_duplicates_use_mapset_new: "elixir.gotta-snatch-em-all.remove_duplicates_use_mapset_new", - gotta_snatch_em_all_remove_duplicates_use_enum_sort: "elixir.gotta-snatch-em-all.remove_duplicates_use_enum_sort", - gotta_snatch_em_all_remove_duplicates_do_not_use_enum_uniq: "elixir.gotta-snatch-em-all.remove_duplicates_do_not_use_enum_uniq", - gotta_snatch_em_all_extra_cards_use_mapset_difference_and_size: "elixir.gotta-snatch-em-all.extra_cards_use_mapset_difference_and_size", - gotta_snatch_em_all_boring_cards_use_mapset_intersection: "elixir.gotta-snatch-em-all.boring_cards_use_mapset_intersection", - gotta_snatch_em_all_boring_cards_use_enum_sort: "elixir.gotta-snatch-em-all.boring_cards_use_enum_sort", - gotta_snatch_em_all_boring_cards_use_enum_reduce: "elixir.gotta-snatch-em-all.boring_cards_use_enum_reduce", - gotta_snatch_em_all_total_cards_use_mapset_union_and_size: "elixir.gotta-snatch-em-all.total_cards_use_mapset_union_and_size", - gotta_snatch_em_all_total_cards_use_enum_reduce: "elixir.gotta-snatch-em-all.total_cards_use_enum_reduce", - gotta_snatch_em_all_split_shiny_cards_use_enum_sort: "elixir.gotta-snatch-em-all.shiny_cards_use_enum_sort", - gotta_snatch_em_all_split_shiny_cards_use_string_starts_with: "elixir.gotta-snatch-em-all.shiny_cards_use_string_starts_with", + gotta_snatch_em_all_add_card_use_mapset_member_and_put: + "elixir.gotta-snatch-em-all.add_card_use_mapset_member_and_put", + gotta_snatch_em_all_trade_card_use_mapset_member_put_and_delete: + "elixir.gotta-snatch-em-all.trade_card_use_mapset_member_put_and_delete", + gotta_snatch_em_all_remove_duplicates_use_mapset_new: + "elixir.gotta-snatch-em-all.remove_duplicates_use_mapset_new", + gotta_snatch_em_all_remove_duplicates_use_enum_sort: + "elixir.gotta-snatch-em-all.remove_duplicates_use_enum_sort", + gotta_snatch_em_all_remove_duplicates_do_not_use_enum_uniq: + "elixir.gotta-snatch-em-all.remove_duplicates_do_not_use_enum_uniq", + gotta_snatch_em_all_extra_cards_use_mapset_difference_and_size: + "elixir.gotta-snatch-em-all.extra_cards_use_mapset_difference_and_size", + gotta_snatch_em_all_boring_cards_use_mapset_intersection: + "elixir.gotta-snatch-em-all.boring_cards_use_mapset_intersection", + gotta_snatch_em_all_boring_cards_use_enum_sort: + "elixir.gotta-snatch-em-all.boring_cards_use_enum_sort", + gotta_snatch_em_all_boring_cards_use_enum_reduce: + "elixir.gotta-snatch-em-all.boring_cards_use_enum_reduce", + gotta_snatch_em_all_total_cards_use_mapset_union_and_size: + "elixir.gotta-snatch-em-all.total_cards_use_mapset_union_and_size", + gotta_snatch_em_all_total_cards_use_enum_reduce: + "elixir.gotta-snatch-em-all.total_cards_use_enum_reduce", + gotta_snatch_em_all_split_shiny_cards_use_enum_sort: + "elixir.gotta-snatch-em-all.shiny_cards_use_enum_sort", + gotta_snatch_em_all_split_shiny_cards_use_string_starts_with: + "elixir.gotta-snatch-em-all.shiny_cards_use_string_starts_with", # Guessing Game Comments guessing_game_use_default_argument: "elixir.guessing-game.use_default_argument", diff --git a/lib/elixir_analyzer/test_suite/gotta-snatch-em-all.ex b/lib/elixir_analyzer/test_suite/gotta-snatch-em-all.ex index ff45e6ce..96de42d4 100644 --- a/lib/elixir_analyzer/test_suite/gotta-snatch-em-all.ex +++ b/lib/elixir_analyzer/test_suite/gotta-snatch-em-all.ex @@ -35,7 +35,7 @@ defmodule ElixirAnalyzer.TestSuite.GottaSnatchEmAll do suppress_if "trade_card uses MapSet.member?", :fail end - assert_call "trade_card uses MapSet.delete" do + assert_call "trade_card uses MapSet.delete" do type :essential calling_fn module: GottaSnatchEmAll, name: :trade_card called_fn module: MapSet, name: :delete