diff --git a/.reek.yml b/.reek.yml
index ad749c6..5d7fa4e 100644
--- a/.reek.yml
+++ b/.reek.yml
@@ -23,6 +23,8 @@ detectors:
- initialize
- Skunk::Cli::Application#execute
- Skunk::Cli::Options::Argv#parse
+ - Skunk::Analysis#test_module?
+ - add_mock_methods_to_module
TooManyInstanceVariables:
exclude:
- Skunk::Generator::Html::FileData
@@ -38,6 +40,8 @@ detectors:
- Skunk::Command::StatusSharer#share_url_empty?
- Skunk::Configuration#supported_format?
- Skunk::Configuration#supported_formats
+ - Skunk::Analysis#test_module?
+ - Skunk::ConfigTest#setup
ManualDispatch:
exclude:
- Skunk::Config#self.method_missing
@@ -45,3 +49,11 @@ detectors:
BooleanParameter:
exclude:
- Skunk::Config#self.respond_to_missing?
+ DuplicateMethodCall:
+ exclude:
+ - Skunk::ConfigTest#test_add_format_ignores_duplicates
+ FeatureEnvy:
+ exclude:
+ - Skunk::Command::StatusReporter#table
+ - Skunk::Generator::HtmlReport#create_directories_and_files
+ - add_mock_methods_to_module
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index e101f19..cc7705f 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
-# on 2025-10-17 11:20:00 UTC using RuboCop version 1.81.1.
+# on 2025-10-17 16:20:40 UTC using RuboCop version 1.81.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@@ -36,11 +36,11 @@ Lint/MissingSuper:
Metrics/AbcSize:
Max: 18
-# Offense count: 8
+# Offense count: 12
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
# AllowedMethods: refine
Metrics/BlockLength:
- Max: 82
+ Max: 233
# Offense count: 2
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4cbe885..e6bc057 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## main [(unreleased)](https://github.com/fastruby/skunk/compare/v0.5.4...HEAD)
+* [REFACTOR: Centralize Skunk analysis into RubyCritic module](https://github.com/fastruby/skunk/pull/127)
* [FEATURE: Add Skunk HTML Report](https://github.com/fastruby/skunk/pull/123)
* [FEATURE: Add Skunk::Config class](https://github.com/fastruby/skunk/pull/123)
* [FEATURE: Add Ruby 3.4 compatibility](https://github.com/fastruby/skunk/pull/124)
diff --git a/lib/skunk/commands/status_reporter.rb b/lib/skunk/commands/status_reporter.rb
index be43eef..315347a 100644
--- a/lib/skunk/commands/status_reporter.rb
+++ b/lib/skunk/commands/status_reporter.rb
@@ -10,6 +10,10 @@ module Command
class StatusReporter < RubyCritic::Command::StatusReporter
attr_accessor :analysed_modules
+ def initialize(options = {})
+ super(options)
+ end
+
HEADINGS = %w[file skunk_score churn_times_cost churn cost coverage].freeze
HEADINGS_WITHOUT_FILE = HEADINGS - %w[file]
HEADINGS_WITHOUT_FILE_WIDTH = HEADINGS_WITHOUT_FILE.size * 17 # padding
@@ -38,36 +42,27 @@ def update_status_message
private
def analysed_modules_count
- @analysed_modules_count ||= non_test_modules.count
- end
-
- def non_test_modules
- @non_test_modules ||= analysed_modules.reject do |a_module|
- module_path = a_module.pathname.dirname.to_s
- module_path.start_with?("test", "spec") || module_path.end_with?("test", "spec")
- end
+ analysed_modules.analysed_modules_count
end
def worst
- @worst ||= sorted_modules.first
+ analysed_modules.worst_module
end
def sorted_modules
- @sorted_modules ||= non_test_modules.sort_by(&:skunk_score).reverse!
+ analysed_modules.sorted_modules
end
def total_skunk_score
- @total_skunk_score ||= non_test_modules.sum(&:skunk_score)
+ analysed_modules.skunk_score_total
end
def total_churn_times_cost
- non_test_modules.sum(&:churn_times_cost)
+ analysed_modules.total_churn_times_cost
end
def skunk_score_average
- return 0 if analysed_modules_count.zero?
-
- (total_skunk_score.to_d / analysed_modules_count).to_f.round(2)
+ analysed_modules.skunk_score_average
end
def table_options
diff --git a/lib/skunk/generators/html/overview.rb b/lib/skunk/generators/html/overview.rb
index 1accdfe..78e7d2b 100644
--- a/lib/skunk/generators/html/overview.rb
+++ b/lib/skunk/generators/html/overview.rb
@@ -3,7 +3,8 @@
require "rubycritic/generators/html/base"
require "skunk/generators/html/path_truncator"
-require "skunk/generators/html/skunk_data"
+require "skunk/generators/html/file_data"
+require "skunk/rubycritic/analysed_modules_collection"
module Skunk
module Generator
@@ -19,7 +20,8 @@ def self.erb_template(template_path)
def initialize(analysed_modules)
@analysed_modules = analysed_modules
- @data = SkunkData.new(analysed_modules)
+ @generated_at = Time.now.strftime("%Y-%m-%d %H:%M:%S")
+ @skunk_version = Skunk::VERSION
end
def file_name
@@ -29,6 +31,24 @@ def file_name
def render
TEMPLATE.result(binding)
end
+
+ def analysed_modules_count
+ @analysed_modules.analysed_modules_count
+ end
+
+ def skunk_score_total
+ @analysed_modules.skunk_score_total
+ end
+
+ def skunk_score_average
+ @analysed_modules.skunk_score_average
+ end
+
+ def files
+ @files ||= @analysed_modules.sorted_modules.map do |module_data|
+ FileData.new(module_data)
+ end
+ end
end
end
end
diff --git a/lib/skunk/generators/html/skunk_data.rb b/lib/skunk/generators/html/skunk_data.rb
deleted file mode 100644
index 19eadb0..0000000
--- a/lib/skunk/generators/html/skunk_data.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-require "skunk/generators/html/file_data"
-require "skunk/generators/html/path_truncator"
-
-module Skunk
- module Generator
- module Html
- # Data object for the HTML overview report
- class SkunkData
- attr_reader :generated_at, :skunk_version,
- :analysed_modules_count, :skunk_score_total, :skunk_score_average,
- :worst_pathname, :worst_score, :files
-
- def initialize(analysed_modules)
- @analysed_modules = analysed_modules
- @generated_at = Time.now.strftime("%Y-%m-%d %H:%M:%S")
- @skunk_version = Skunk::VERSION
-
- @analysed_modules_count = non_test_modules.count
- @skunk_score_total = non_test_modules.sum(&:skunk_score)
- @skunk_score_average = calculate_average
- @worst_pathname = PathTruncator.truncate(find_worst_module&.pathname)
- @worst_score = find_worst_module&.skunk_score
- @files = build_files
- end
-
- private
-
- def non_test_modules
- @non_test_modules ||= @analysed_modules.reject do |a_module|
- module_path = a_module.pathname.dirname.to_s
- module_path.start_with?("test", "spec") || module_path.end_with?("test", "spec")
- end
- end
-
- def calculate_average
- return 0 if @analysed_modules_count.zero?
-
- (@skunk_score_total.to_d / @analysed_modules_count).round(2)
- end
-
- def find_worst_module
- @find_worst_module ||= sorted_modules.first
- end
-
- def sorted_modules
- @sorted_modules ||= non_test_modules.sort_by(&:skunk_score).reverse!
- end
-
- def build_files
- @build_files ||= sorted_modules.map do |module_data|
- FileData.new(module_data)
- end
- end
- end
- end
- end
-end
diff --git a/lib/skunk/generators/html/templates/skunk_overview.html.erb b/lib/skunk/generators/html/templates/skunk_overview.html.erb
index 9fea17e..cee421a 100644
--- a/lib/skunk/generators/html/templates/skunk_overview.html.erb
+++ b/lib/skunk/generators/html/templates/skunk_overview.html.erb
@@ -242,15 +242,15 @@