credo icon indicating copy to clipboard operation
credo copied to clipboard

Add StrictModuleDirectiveScope check

Open stevebissett opened this issue 4 months ago • 1 comments

Summary

This PR adds a new opt-in readability check StrictModuleDirectiveScope that encourages declaring module directives (alias, require, import, use) at the module level rather than inside function bodies.

Closes #1222

Motivation

Inline directives can make code harder to follow and obscure module dependencies. By requiring all directives at the module level, readers can quickly understand a module's dependencies by looking at the top of the file.

This addresses the need described in #1222 for teams that value explicit, discoverable dependencies over tightly-scoped imports.

Implementation

The check detects directives in:

  • All function types (def, defp, defmacro, defmacrop)
  • All control structures (if/unless/case/cond/with/try)
  • Anonymous functions
  • For comprehensions

Configuration Options

  • directives - List of directive types to check (default: all four)
  • allow_in_private_functions - Skip checking private functions (default: false)
  • allow_in_test_macros - Skip checking test blocks (default: true)
  • allow_in_quote_blocks - Skip checking quote blocks (default: true)
  • exclude_functions - Regex patterns to exclude specific functions

Example

# Will trigger issue
defmodule MyModule do
  def process_data(data) do
    alias MyApp.DataProcessor
    DataProcessor.process(data)
  end
end

# Preferred style
defmodule MyModule do
  alias MyApp.DataProcessor
  
  def process_data(data) do
    DataProcessor.process(data)
  end
end

Configuration Example

# In .credo.exs
{Credo.Check.Readability.StrictModuleDirectiveScope, [
  directives: [:alias, :require],  # Only check these two
  allow_in_private_functions: true,
  exclude_functions: [~r/^render/]  # Allow in LiveView render functions
]}

Test Coverage

  • 37 test cases covering all directive types, control structures, and configuration options
  • Tests for real-world patterns (LiveView, ExUnit test blocks)
  • Edge case handling (anonymous functions, comprehensions, nested structures)

Checklist

  • [x] Implementation follows Credo check patterns
  • [x] Comprehensive test suite with 37+ test cases
  • [x] Check registered in .credo.exs as disabled/opt-in
  • [x] Extensive documentation with rationale and examples
  • [x] Marked as controversial (disabled by default)
  • [x] Configuration examples provided

stevebissett avatar Oct 16 '25 14:10 stevebissett

Trying to discuss this in #1222 - surprised there is a PR for it already.

Out of curiosity: Did you AI generate this?

rrrene avatar Oct 16 '25 19:10 rrrene