# frozen_string_literal: true require "core" require "refinements/string" module Git module Lint module Analyzers # An abstract class which provides basic functionality for all analyzers to inherit from. class Abstract include Import[:settings, :environment] using Refinements::String LEVELS = %w[warn error].freeze BODY_OFFSET = 3 def self.id = to_s.delete_prefix!("Git::Lint::Analyzers").snakecase def self.label = to_s.delete_prefix("Git::Lint::Analyzers").titleize def self.build_issue_line(index, line) = {number: index + BODY_OFFSET, content: line} attr_reader :commit def initialize(commit, **) super(**) @commit = commit @filter_list = load_filter_list end def severity settings.public_send("#{self.class.id}_severity".sub("commit_", "commits_")) .tap { |level| fail Errors::Severity, level unless LEVELS.include? level } end def valid? = fail NoMethodError, "The `##{__method__}` method must be implemented." def invalid? = !valid? def warning? = invalid? && severity == "warn" def error? = invalid? && severity == "error" def issue = fail NoMethodError, "The `##{__method__}` method must be implemented." protected attr_reader :filter_list def load_filter_list = Core::EMPTY_ARRAY def affected_commit_body_lines commit.body_lines.each.with_object([]).with_index do |(line, lines), index| lines << self.class.build_issue_line(index, line) if invalid_line? line end end def affected_commit_trailers commit.trailers .each .with_object([]) .with_index(commit.body_lines.size) do |(trailer, trailers), index| next unless invalid_line? trailer trailers << self.class.build_issue_line(index, trailer.to_s) end end def invalid_line?(*) fail NoMethodError, "The `.#{__method__}` method must be implemented." end end end end end