Class: DevDoc::Test::Lints::NoFileExcludesChecker

Inherits:
Object
  • Object
show all
Defined in:
lib/dev_doc/test/lints/no_file_excludes.rb

Overview

Framework-agnostic check: reads a ‘.rubocop.yml`, walks every `Exclude:` list under each top-level section, and returns offender descriptions for entries that are literal file paths (no glob characters) outside the configured allowlist.

Wrapped by the Minitest module ‘NoFileExcludes` below — see that module for the rationale.

Constant Summary collapse

DEFAULT_ALLOWED_FILES =

File paths universally exempt because they’re auto-generated and nobody reads them like source code. Consumer projects can extend this via the per-project override on the ‘NoFileExcludes` module.

%w[db/schema.rb].freeze
GLOB_CHARACTERS =
/[*?\[\]{}]/.freeze
MissingFile =

Sentinel returned by ‘#offenders` when the `.rubocop.yml` doesn’t exist. Distinguishable from ‘[]` (file present, all good) so the Minitest wrapper can `skip` rather than `assert`.

Module.new

Instance Method Summary collapse

Constructor Details

#initialize(rubocop_yml_path, allowed_files: DEFAULT_ALLOWED_FILES) ⇒ NoFileExcludesChecker

Returns a new instance of NoFileExcludesChecker.



26
27
28
29
# File 'lib/dev_doc/test/lints/no_file_excludes.rb', line 26

def initialize(rubocop_yml_path, allowed_files: DEFAULT_ALLOWED_FILES)
  @rubocop_yml_path = rubocop_yml_path
  @allowed_files = allowed_files.to_set
end

Instance Method Details

#offendersObject

Returns an Array<String> of offender descriptions (one per literal-path entry in any ‘Exclude:` list), `[]` if all entries are globs or allowlisted, or `MissingFile` if the `.rubocop.yml` doesn’t exist.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/dev_doc/test/lints/no_file_excludes.rb', line 35

def offenders
  return MissingFile unless @rubocop_yml_path.exist?

  # YAML.safe_load returns nil for an empty file. Rubocop config
  # is a flat top-level hash; `Exclude:` keys live one level down.
  (YAML.safe_load(@rubocop_yml_path.read) || {}).each_with_object([]) do |(section, value), acc|
    next unless value.is_a?(Hash)

    Array(value['Exclude']).each do |entry|
      next unless entry.is_a?(String)
      next if entry.match?(GLOB_CHARACTERS)
      next if @allowed_files.include?(entry)

      acc << "  #{section}: Exclude includes literal file #{entry.inspect}"
    end
  end
end