rrrene / credo

A static code analysis tool for the Elixir language with a focus on code consistency and teaching.
http://credo-ci.org/
MIT License
4.91k stars 415 forks source link

Question around the plugin #1147

Open epinault opened 1 month ago

epinault commented 1 month ago

Environment

What were you trying to do?

Hello, I have a question regarding the plugin API. I use a basic plugin that basically load a default config file. plugin is then configured and used and works correctly. So does something like

  import Credo.Plugin

  @config_file File.read!(".credo.exs")

  def init(exec) do
    exec = register_default_config(exec, @config_file) 
  end

I am trying to expand that plugin to allow more dynamic behavior, especially with regards of the being to add custom check dynamically.

When I try to modify the Execution returned by the plugin, it does not seems to take any effects at all (say for example to try to see if that would work I turned off all check on a repo where the check would currently flag) but it s not working

  def init(exec) do
    exec = register_default_config(exec, @config_file) 
   %Credo.Execution{exec | checks: %{enabled: []}}
  end

or

  def init(exec) do
    register_default_config(exec, @config_file) |> append_task(:initialize_plugins, MyCustomTask)
  end

And MyCustomTask would be basically in the call callback, do similar thing to manipulate the checks

 def call(exec, _opts) do
   %Credo.Execution{exec | checks: %{enabled: []}}
end

I have tried a different approach by using append_task at different part of the webhooks, but again modifying the checks, seems to have no effects

So I am wondering if its even possible to modify them after the register_default_config(exec, @config_file). I don t even see an api to modify the checks but since the Execution is just a struct, I thought I could modify it somehow in the pipeline .. but not working . Do you have a suggestion on how we could approach this to make it work? what am I missing?

Only thing I can think off is modifying the file dynamically prior to calling the register (but that means doing Code.eval_file etc... )

Expected outcome

Need a way to add dynamically some plugin based on configuration passed to the plugin

Actual outcome

rrrene commented 1 month ago

Hi,

your example does not work because Credo's loading and validating of checks runs after your code. So your change to the exec struct is simply overwritten.

You can probably achieve what you are describing by prepending your task to :run_command (so the task you register is running before the called Credo command):

prepend_task(exec, :run_command, __MODULE__.ClearChecks)

then you have to set/reset the checks like this (not just setting :enabled):

def call(exec, _opts) do
  %Execution{exec | checks: %{enabled: [], disabled: [], extra: []}}
end

The pipeline groups are described here: https://hexdocs.pm/credo/Credo.Plugin.html#prepend_task/3

epinault commented 4 weeks ago

ah! thanks! I think the set/reset really seems to fix the the problem I was seeing. I guess I could not just partial update.

thanks you for the help on this !