Class: Yard::Lint::ConfigLoader

Inherits:
Object
  • Object
show all
Defined in:
lib/yard/lint/config_loader.rb

Overview

Handles loading and merging of configuration files with inheritance support

Constant Summary collapse

INHERITANCE_KEYS =

Inheritance keys to skip when merging configs

%w[inherit_from inherit_gem].freeze
ALL_VALIDATORS =

All validator names (auto-discovered from codebase structure)

discover_validators.values.flatten.freeze
DEFAULT_VALIDATOR_CONFIG =

Default configuration for each validator

{
  'Enabled' => true,
  'Severity' => nil, # Will use validator's default or department fallback
  'Exclude' => []
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ ConfigLoader

Returns a new instance of ConfigLoader.

Parameters:

  • path (String)

    path to configuration file



108
109
110
111
# File 'lib/yard/lint/config_loader.rb', line 108

def initialize(path)
  @path = path
  @loaded_files = []
end

Class Method Details

.discover_validatorsHash{String => Array<String>}

Auto-discover validators from the codebase Scans the validators directory and loads all validator modules that have an .id method and .defaults method (indicating they’re valid validators)

Returns:

  • (Hash{String => Array<String>})

    hash of category names to validator names



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/yard/lint/config_loader.rb', line 41

def discover_validators
  categories = Hash.new { |h, k| h[k] = [] }

  validators_path = File.join(__dir__, 'validators')

  # Find all validator module files (e.g., validators/tags/order.rb)
  Dir.glob(File.join(validators_path, '*', '*.rb')).each do |file_path|
    # Require the validator module file to ensure it's loaded
    require file_path

    # Extract category and validator name from path
    # e.g., .../validators/tags/order.rb -> ['tags', 'order']
    relative_path = file_path.sub("#{validators_path}/", '')
    parts = relative_path.sub('.rb', '').split('/')
    category_dir = parts[0]
    validator_dir = parts[1]

    # Convert to proper casing:
    # 'tags' -> 'Tags', 'undocumented_objects' -> 'UndocumentedObjects'
    category = category_dir.split('_').map(&:capitalize).join
    validator = validator_dir.split('_').map(&:capitalize).join

    # Construct the validator name
    validator_name = "#{category}/#{validator}"

    # Verify it's a valid validator by checking if it has a Config class
    cfg = validator_config(validator_name)
    # Every validator must have a Config with id and defaults
    categories[category] << validator_name if cfg && cfg.id && cfg.defaults
  end

  # Sort for consistent ordering
  categories.transform_values(&:sort).sort.to_h
end

.load(path) ⇒ Hash

Load configuration from file with inheritance support

Parameters:

  • path (String)

    path to configuration file

Returns:

  • (Hash)

    merged configuration hash



79
80
81
# File 'lib/yard/lint/config_loader.rb', line 79

def load(path)
  new(path).load
end

.load_yaml_file(path) ⇒ Hash

Load a YAML config file with alias/anchor support and clean errors. Psych 4+ rejects aliases by default, breaking the common RuboCop-style shared-section idiom; malformed YAML would otherwise escape as a raw Psych::SyntaxError backtrace.

Parameters:

  • path (String)

    path to the YAML file

Returns:

  • (Hash)

    parsed YAML, or an empty hash for empty files

Raises:



90
91
92
93
94
# File 'lib/yard/lint/config_loader.rb', line 90

def load_yaml_file(path)
  YAML.load_file(path, aliases: true) || {}
rescue Psych::SyntaxError => e
  raise Errors::InvalidConfigError, "Invalid YAML in #{path}: #{e.message}"
end

.validator_config(validator_name) ⇒ Class?

Get the validator config for a given validator name Dynamically resolves the config class based on the validator name

Parameters:

  • validator_name (String)

    validator name (e.g., ‘Tags/Order’)

Returns:

  • (Class, nil)

    validator config class or nil if doesn’t exist



29
30
31
32
33
34
35
# File 'lib/yard/lint/config_loader.rb', line 29

def validator_config(validator_name)
  namespace = validator_module(validator_name)
  return nil unless namespace

  # Return the Config class from within the validator namespace
  namespace.const_defined?(:Config) ? namespace.const_get(:Config) : nil
end

.validator_module(validator_name) ⇒ Module?

Get the validator namespace module for a given validator name

Parameters:

  • validator_name (String)

    validator name (e.g., ‘Tags/Order’)

Returns:

  • (Module, nil)

    validator namespace module or nil if doesn’t exist



14
15
16
17
18
19
20
21
22
23
# File 'lib/yard/lint/config_loader.rb', line 14

def validator_module(validator_name)
  category, name = validator_name.split('/')
  module_path = "Validators::#{category}::#{name}"

  module_path.split('::').reduce(Yard::Lint) do |mod, const_name|
    return nil unless mod.const_defined?(const_name)

    mod.const_get(const_name)
  end
end

Instance Method Details

#loadHash

Load and merge configuration with inheritance

Returns:

  • (Hash)

    final merged configuration



115
116
117
# File 'lib/yard/lint/config_loader.rb', line 115

def load
  load_file(@path)
end