zf

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

spec_with_struct.ex (1619B)


      1 defmodule Credo.Check.Warning.SpecWithStruct do
      2   use Credo.Check,
      3     base_priority: :normal,
      4     category: :warning,
      5     explanations: [
      6       check: """
      7       Structs create compile-time dependencies between modules.  Using a struct in a spec
      8       will cause the module to be recompiled whenever the struct's module changes.
      9 
     10       It is preferable to define and use `MyModule.t()` instead of `%MyModule{}` in specs.
     11 
     12       Example:
     13 
     14           # preferred
     15           @spec a_function(MyModule.t()) :: any
     16 
     17           # NOT preferred
     18           @spec a_function(%MyModule{}) :: any
     19       """
     20     ]
     21 
     22   alias Credo.Code.Name
     23 
     24   @doc false
     25   @impl true
     26   def run(%SourceFile{} = source_file, params) do
     27     issue_meta = IssueMeta.for(source_file, params)
     28     Credo.Code.prewalk(source_file, &traverse(&1, &2, issue_meta))
     29   end
     30 
     31   defp traverse({:@, meta, [{:spec, _, args}]}, issues, issue_meta) do
     32     case Macro.prewalk(args, [], &find_structs/2) do
     33       {ast, []} ->
     34         {ast, issues}
     35 
     36       {ast, structs} ->
     37         issues =
     38           Enum.reduce(structs, issues, fn curr, acc ->
     39             options = [
     40               message: "Struct %#{curr}{} found in @spec",
     41               trigger: "%#{curr}{}",
     42               line_no: meta[:line]
     43             ]
     44 
     45             [format_issue(issue_meta, options) | acc]
     46           end)
     47 
     48         {ast, issues}
     49     end
     50   end
     51 
     52   defp traverse(ast, issues, _issue_meta) do
     53     {ast, issues}
     54   end
     55 
     56   defp find_structs({:%, _, [{:__aliases__, _, _} = aliases | _]} = ast, acc) do
     57     {ast, [Name.full(aliases) | acc]}
     58   end
     59 
     60   defp find_structs(ast, acc) do
     61     {ast, acc}
     62   end
     63 end