Module: DevDoc::Test::Lints::NoFileExcludes
- Defined in:
- lib/dev_doc/test/lints/no_file_excludes.rb
Overview
Reject literal-file entries in any ‘Exclude:` list under `.rubocop.yml`.
## Rationale A literal-path ‘Exclude:` makes the suppression invisible to anyone reading the excluded file. They see the violating code, see no `# rubocop:disable` annotation near it, and reasonably conclude the pattern is acceptable for new code in the same file. That sets the wrong expectation and lets violations multiply.
Inline ‘# rubocop:disable Cop/Name` at the violation line(s) keeps the suppression visible to anyone reading the code AND scopes it to the specific lines — a fresh violation in the same file still gets flagged. The rationale for the suppression lives next to the code it describes, so a future reader sees it without having to cross-check `.rubocop.yml`.
Globs (‘vendor/*/`, `db/migrate/*/.rb`, `bin/*`) remain fine because they target a category, not a file someone might be reading.
❌ Hides the suppression from readers of the file
DevDoc/Migration/AvoidColumnDefault:
Exclude:
- "db/migrate/20260505035728_create_pr_reviews.rb"
✔ Visible inline, scoped to the specific line(s)
# db/migrate/20260505035728_create_pr_reviews.rb
t.jsonb :diff_files, default: [] # rubocop:disable DevDoc/Migration/AvoidColumnDefault
✔ Glob — still acceptable, targets a category not a specific file
AllCops:
Exclude:
- "vendor/**/*"
## Usage Include this module in a Minitest test class. To allowlist additional auto-generated literal paths (e.g. a project-specific generated file), redefine ‘ALLOWED_FILE_EXCLUDES` on the test class.
class RubocopConfigTest < ActiveSupport::TestCase
include DevDoc::Test::Lints::NoFileExcludes
# ALLOWED_FILE_EXCLUDES = %w[db/schema.rb Gemfile.lock].freeze
end
Constant Summary collapse
- ALLOWED_FILE_EXCLUDES =
Default allowlist. Per-project override: redefine the constant on the test class that includes this module.
NoFileExcludesChecker::DEFAULT_ALLOWED_FILES
Instance Method Summary collapse
Instance Method Details
#test_no_file_excludes_in_rubocop_yml ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/dev_doc/test/lints/no_file_excludes.rb', line 105 def test_no_file_excludes_in_rubocop_yml result = NoFileExcludesChecker .new(rubocop_yml_path, allowed_files: self.class::ALLOWED_FILE_EXCLUDES) .offenders skip "no #{rubocop_yml_path} found" if result == NoFileExcludesChecker::MissingFile assert result.empty?, "`.rubocop.yml` Exclude lists must contain only globs " \ "(category patterns), not literal file paths. A literal-path " \ "exclude hides the suppression from readers of the file. " \ "Use `# rubocop:disable Cop/Name` at the violation line(s) " \ "instead — visible to readers, scoped to the specific lines.\n\n" \ "Offenders:\n#{result.join("\n")}" end |