zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

predicate_function_names.ex (2804B)


      1 defmodule Credo.Check.Readability.PredicateFunctionNames do
      2   use Credo.Check,
      3     base_priority: :high,
      4     explanations: [
      5       check: """
      6       Predicate functions/macros should be named accordingly:
      7 
      8       * For functions, they should end in a question mark.
      9 
     10           # preferred
     11 
     12           defp user?(cookie) do
     13           end
     14 
     15           defp has_attachment?(mail) do
     16           end
     17 
     18           # NOT preferred
     19 
     20           defp is_user?(cookie) do
     21           end
     22 
     23           defp is_user(cookie) do
     24           end
     25 
     26       * For guard-safe macros they should have the prefix `is_` and not end in a question mark.
     27 
     28           # preferred
     29 
     30           defmacro is_user(cookie) do
     31           end
     32 
     33           # NOT preferred
     34 
     35           defmacro is_user?(cookie) do
     36           end
     37 
     38           defmacro user?(cookie) do
     39           end
     40 
     41       Like all `Readability` issues, this one is not a technical concern.
     42       But you can improve the odds of others reading and liking your code by making
     43       it easier to follow.
     44       """
     45     ]
     46 
     47   @def_ops [:def, :defp, :defmacro]
     48 
     49   @doc false
     50   @impl true
     51   def run(%SourceFile{} = source_file, params) do
     52     issue_meta = IssueMeta.for(source_file, params)
     53 
     54     Credo.Code.prewalk(source_file, &traverse(&1, &2, issue_meta))
     55   end
     56 
     57   # TODO: consider for experimental check front-loader (ast)
     58   # NOTE: see below for how we want to avoid `defp = "my_variable"` definitions
     59   for op <- @def_ops do
     60     # catch variables named e.g. `defp`
     61     defp traverse({unquote(op), _meta, nil} = ast, issues, _issue_meta) do
     62       {ast, issues}
     63     end
     64 
     65     defp traverse(
     66            {unquote(op) = op, _meta, arguments} = ast,
     67            issues,
     68            issue_meta
     69          ) do
     70       {ast, issues_for_definition(op, arguments, issues, issue_meta)}
     71     end
     72   end
     73 
     74   defp traverse(ast, issues, _issue_meta) do
     75     {ast, issues}
     76   end
     77 
     78   defp issues_for_definition(op, body, issues, issue_meta) do
     79     case Enum.at(body, 0) do
     80       {name, meta, nil} ->
     81         issues_for_name(op, name, meta, issues, issue_meta)
     82 
     83       _ ->
     84         issues
     85     end
     86   end
     87 
     88   defp issues_for_name(_op, name, meta, issues, issue_meta) do
     89     name = to_string(name)
     90 
     91     cond do
     92       String.starts_with?(name, "is_") && String.ends_with?(name, "?") ->
     93         [
     94           issue_for(issue_meta, meta[:line], name, :predicate_and_question_mark)
     95           | issues
     96         ]
     97 
     98       String.starts_with?(name, "is_") ->
     99         [issue_for(issue_meta, meta[:line], name, :only_predicate) | issues]
    100 
    101       true ->
    102         issues
    103     end
    104   end
    105 
    106   defp issue_for(issue_meta, line_no, trigger, _) do
    107     format_issue(
    108       issue_meta,
    109       message:
    110         "Predicate function names should not start with 'is', and should end in a question mark.",
    111       trigger: trigger,
    112       line_no: line_no
    113     )
    114   end
    115 end