class Goodcheck::ConfigLoader

Constants

Schema

Attributes

content[R]
import_loader[R]
path[R]
printed_warnings[R]
stderr[R]

Public Class Methods

new(path:, content:, stderr:, import_loader:) click to toggle source
# File lib/goodcheck/config_loader.rb, line 214
def initialize(path:, content:, stderr:, import_loader:)
  @path = path
  @content = content
  @stderr = stderr
  @printed_warnings = Set.new
  @import_loader = import_loader
end

Public Instance Methods

case_sensitive?(pattern) click to toggle source
# File lib/goodcheck/config_loader.rb, line 445
def case_sensitive?(pattern)
  return true if pattern.is_a?(String)
  case
  when pattern.key?(:case_sensitive)
    pattern[:case_sensitive]
  when pattern.key?(:case_insensitive)
    print_warning_once "👻 `case_insensitive` option is deprecated. Use `case_sensitive` option instead."
    !pattern[:case_insensitive]
  else
    true
  end
end
load() click to toggle source
# File lib/goodcheck/config_loader.rb, line 222
def load
  Goodcheck.logger.info "Loading configuration: #{path}"
  Schema.config.coerce(content)

  rules = []

  load_rules(rules, array(content[:rules]))

  Array(content[:import]).each do |import|
    load_import rules, import
  end

  Config.new(
    rules: rules,
    exclude_paths: Array(content[:exclude]),
    exclude_binary: content[:exclude_binary],
    severity: content[:severity]
  )
end
load_globs(globs) click to toggle source
# File lib/goodcheck/config_loader.rb, line 353
def load_globs(globs)
  globs.map do |glob|
    case glob
    when String
      Glob.new(pattern: glob, encoding: nil, exclude: nil)
    when Hash
      Glob.new(pattern: glob[:pattern], encoding: glob[:encoding], exclude: glob[:exclude])
    end
  end
end
load_import(rules, import) click to toggle source
# File lib/goodcheck/config_loader.rb, line 250
def load_import(rules, import)
  Goodcheck.logger.info "Importing rules from #{import}"

  import_loader.load(import) do |content, filename|
    json = JSON.parse(JSON.dump(YAML.safe_load(content, filename: filename)), symbolize_names: true)

    Schema.rules.coerce json
    load_rules(rules, json)
  end
end
load_pattern(pattern) click to toggle source
# File lib/goodcheck/config_loader.rb, line 364
def load_pattern(pattern)
  case pattern
  when String
    case (pat = load_string_pattern(pattern))
    when String
      Pattern::Literal.new(source: pat, case_sensitive: true)
    when ::Regexp
      Pattern::Regexp.new(source: pattern,
                          regexp: pat,
                          multiline: pat.options & ::Regexp::MULTILINE == ::Regexp::MULTILINE,
                          case_sensitive: !pat.casefold?)
    end
  when Hash
    if pattern[:glob]
      print_warning_once "🌏 Pattern with glob is deprecated: globs are ignored at all."
    end

    case
    when pattern[:literal]
      cs = case_sensitive?(pattern)
      literal = pattern[:literal]
      Pattern::Literal.new(source: literal, case_sensitive: cs)
    when pattern[:regexp]
      regexp = pattern[:regexp]
      cs = case_sensitive?(pattern)
      multiline = pattern[:multiline]
      Pattern::Regexp.new(source: regexp, case_sensitive: cs, multiline: multiline)
    when pattern[:token]
      tok = pattern[:token]
      cs = case_sensitive?(pattern)
      Pattern::Token.new(source: tok, variables: load_token_vars(pattern[:where]), case_sensitive: cs)
    end
  end
end
load_rule(hash) click to toggle source
# File lib/goodcheck/config_loader.rb, line 261
def load_rule(hash)
  Goodcheck.logger.debug "Loading rule: #{hash[:id]}"

  id = hash[:id]
  triggers = retrieve_triggers(hash)
  justifications = array(hash[:justification])
  message = hash[:message].chomp
  severity = hash[:severity]

  Rule.new(id: id, message: message, justifications: justifications, triggers: triggers, severity: severity)
end
load_rules(rules, array) click to toggle source
# File lib/goodcheck/config_loader.rb, line 242
def load_rules(rules, array)
  array.each do |hash|
    rules << load_rule(hash)
  rescue RegexpError => exn
    raise InvalidPattern, "Invalid pattern of the `#{hash.fetch(:id)}` rule in `#{path}`: #{exn.message}"
  end
end
load_string_pattern(string) click to toggle source
# File lib/goodcheck/config_loader.rb, line 399
def load_string_pattern(string)
  if string =~ /\A\/(.*)\/([im]*)\Z/
    source = $1
    opts = $2
    options = 0
    options |= ::Regexp::IGNORECASE if opts =~ /i/
    options |= ::Regexp::MULTILINE if opts =~ /m/
    ::Regexp.new(source, options)
  else
    string
  end
end
load_token_vars(pattern) click to toggle source
# File lib/goodcheck/config_loader.rb, line 412
def load_token_vars(pattern)
  case pattern
  when Hash
    pattern.each.with_object({}) do |(key, value), hash|
      hash[key.to_sym] = load_var_pattern(value)
    end
  else
    {}
  end
end
load_var_pattern(pattern) click to toggle source
# File lib/goodcheck/config_loader.rb, line 423
def load_var_pattern(pattern)
  if pattern.is_a?(Hash) && pattern[:not]
    negated = true
    pattern = pattern[:not]
  else
    negated = false
  end

  pattern = [] if pattern == true

  patterns = array(pattern).map do |pat|
    case pat
    when String
      load_string_pattern(pat)
    else
      pat
    end
  end

  Pattern::Token::VarPattern.new(patterns: patterns, negated: negated)
end
print_warning_once(message) click to toggle source
retrieve_patterns(hash) click to toggle source
# File lib/goodcheck/config_loader.rb, line 338
def retrieve_patterns(hash)
  if hash.is_a?(Hash) && hash.key?(:not)
    negated = true
    hash = hash[:not]
  else
    negated = false
  end

  if hash.key?(:pattern)
    [array(hash[:pattern]).map {|pat| load_pattern(pat) }, negated]
  else
    [[], false]
  end
end
retrieve_trigger(hash) click to toggle source
# File lib/goodcheck/config_loader.rb, line 325
def retrieve_trigger(hash)
  patterns, negated = retrieve_patterns(hash)
  globs = load_globs(array(hash[:glob]))
  passes = array(hash[:pass])
  fails = array(hash[:fail])

  Trigger.new(patterns: patterns,
              globs: globs,
              passes: passes,
              fails: fails,
              negated: negated)
end
retrieve_triggers(hash) click to toggle source
# File lib/goodcheck/config_loader.rb, line 273
def retrieve_triggers(hash)
  if hash.key?(:trigger)
    array(hash[:trigger]).map do |trigger|
      retrieve_trigger(trigger)
    end
  else
    globs = load_globs(array(hash[:glob]))
    passes = array(hash[:pass])
    fails = array(hash[:fail])

    if hash.key?(:not) || hash.key?(:pattern)
      if hash.key?(:not)
        negated = true
        patterns = array(hash[:not][:pattern])
      else
        negated = false
        patterns = array(hash[:pattern])
      end

      glob_patterns, noglob_patterns = patterns.partition {|pat|
        pat.is_a?(Hash) && pat.key?(:glob)
      }

      skip_fails = !fails.empty? && !glob_patterns.empty?

      glob_patterns.map do |pat|
        Trigger.new(
          patterns: [load_pattern(pat)],
          globs: load_globs(array(pat[:glob])),
          passes: passes,
          fails: [],
          negated: negated
        ).by_pattern!.skips_fail_examples!(skip_fails)
      end.push(
        Trigger.new(
          patterns: noglob_patterns.map {|pat| load_pattern(pat) },
          globs: globs,
          passes: passes,
          fails: glob_patterns.empty? ? fails : [],
          negated: negated
        ).by_pattern!.skips_fail_examples!(skip_fails)
      )
    else
      [Trigger.new(patterns: [],
                   globs: globs,
                   passes: passes,
                   fails: fails,
                   negated: false).by_pattern!]
    end
  end
end