Skip to content

Commit ff8b0f8

Browse files
authored
Move Console Report out of Status Reporter (#128)
* Add analysis class * Move from class to module Refactor Skunk analysis integration by removing the Analysis class and adding its methods directly to RubyCritic::AnalysedModulesCollection. Update related files to utilize the new methods for Skunk score calculations and reporting. * Move Console Report out of Status Reporter The status reporter has a different purpuse in the RubyCritic gem, they also have the specific usage of the Console Report and now we are following the same patters that gem created. - Added support for a new console output format in the FormatValidator module. - Refactored the StatusReporter to provide a simplified status message upon completion of analysis. - Introduced ConsoleReport and Simple classes for generating detailed console reports of analysed modules. - Updated tests to validate new console reporting functionality and ensure expected outputs. - Adjusted existing tests to reflect changes in the status reporting method. * Update StatusReporter class This class used to return the Console message but now it does not have that responsibility and will only return an empty string until we get the GPA Score on Skunk, we will print it as RubyCritic does * Update Status Sharer to use skunk analysis from the collection module * Move Console report * Update CHANGELOG.md
1 parent 2964e95 commit ff8b0f8

23 files changed

+754
-231
lines changed

.rubocop_todo.yml

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This configuration was generated by
22
# `rubocop --auto-gen-config`
3-
# on 2025-10-17 16:20:40 UTC using RuboCop version 1.81.1.
3+
# on 2025-10-17 22:53:06 UTC using RuboCop version 1.81.1.
44
# The point is for the user to remove these configuration records
55
# one by one as the offenses are removed from the code base.
66
# Note that changes in the inspected code, or installation of new
@@ -13,16 +13,9 @@ Gemspec/RequiredRubyVersion:
1313
- 'skunk.gemspec'
1414

1515
# Offense count: 1
16-
# This cop supports safe autocorrection (--autocorrect).
17-
Layout/ClosingHeredocIndentation:
18-
Exclude:
19-
- 'lib/skunk/commands/status_reporter.rb'
20-
21-
# Offense count: 1
22-
# This cop supports safe autocorrection (--autocorrect).
23-
Layout/HeredocIndentation:
16+
Lint/IneffectiveAccessModifier:
2417
Exclude:
25-
- 'lib/skunk/commands/status_reporter.rb'
18+
- 'lib/skunk/generators/console/simple.rb'
2619

2720
# Offense count: 2
2821
# Configuration parameters: AllowedParentClasses.
@@ -31,21 +24,21 @@ Lint/MissingSuper:
3124
- 'lib/skunk/cli/application.rb'
3225
- 'lib/skunk/generators/html/overview.rb'
3326

34-
# Offense count: 1
27+
# Offense count: 4
3528
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
3629
Metrics/AbcSize:
37-
Max: 18
30+
Max: 24
3831

39-
# Offense count: 12
32+
# Offense count: 14
4033
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
4134
# AllowedMethods: refine
4235
Metrics/BlockLength:
43-
Max: 233
36+
Max: 208
4437

45-
# Offense count: 2
38+
# Offense count: 5
4639
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
4740
Metrics/MethodLength:
48-
Max: 13
41+
Max: 18
4942

5043
# Offense count: 1
5144
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
@@ -55,6 +48,16 @@ Naming/VariableNumber:
5548
Exclude:
5649
- 'lib/skunk/commands/status_sharer.rb'
5750

51+
# Offense count: 1
52+
# This cop supports unsafe autocorrection (--autocorrect-all).
53+
# Configuration parameters: EnforcedStyle, EnforcedStyleForClasses, EnforcedStyleForModules.
54+
# SupportedStyles: nested, compact
55+
# SupportedStylesForClasses: ~, nested, compact
56+
# SupportedStylesForModules: ~, nested, compact
57+
Style/ClassAndModuleChildren:
58+
Exclude:
59+
- 'test/test_helper.rb'
60+
5861
# Offense count: 1
5962
# This cop supports unsafe autocorrection (--autocorrect-all).
6063
# Configuration parameters: EnforcedStyle.
@@ -63,3 +66,10 @@ Style/FrozenStringLiteralComment:
6366
Exclude:
6467
- '**/*.arb'
6568
- 'bin/console'
69+
70+
# Offense count: 2
71+
# This cop supports safe autocorrection (--autocorrect).
72+
# Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
73+
# URISchemes: http, https
74+
Layout/LineLength:
75+
Max: 124

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## main [(unreleased)](https://github.com/fastruby/skunk/compare/v0.5.4...HEAD)
99

10+
* [REFACTOR: Move Console Report](https://github.com/fastruby/skunk/pull/128)
1011
* [BUGFIX: Set the right content type in the share HTTP request](https://github.com/fastruby/skunk/pull/129)
1112
* [REFACTOR: Centralize Skunk analysis into RubyCritic module](https://github.com/fastruby/skunk/pull/127)
1213
* [FEATURE: Add Skunk HTML Report](https://github.com/fastruby/skunk/pull/123)

bin/console

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ puts ARGV.inspect
1313
require "skunk/cli/application"
1414
require "skunk/config"
1515

16-
Skunk::Config.formats = %i[json html]
16+
Skunk::Config.formats = %i[json console html]
1717
Skunk::Cli::Application.new(ARGV).execute

lib/skunk/cli/application.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
require "skunk"
77
require "skunk/rubycritic/analysed_module"
8+
require "skunk/rubycritic/analysed_modules_collection"
89
require "skunk/cli/options"
910
require "skunk/command_factory"
1011
require "skunk/commands/status_sharer"

lib/skunk/cli/options/argv.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class Argv < RubyCritic::Cli::Options::Argv
1212
# :reek:Attribute
1313
attr_accessor :output_filename
1414

15-
def parse # rubocop:disable Metrics/MethodLength
15+
def parse
1616
parser.new do |opts|
1717
opts.banner = "Usage: skunk [options] [paths]\n"
1818

lib/skunk/commands/default.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ def report(analysed_modules)
3939
Reporter.generate_report(analysed_modules)
4040

4141
status_reporter.analysed_modules = analysed_modules
42-
status_reporter.score = analysed_modules.score
4342
end
4443
end
4544
end

lib/skunk/commands/status_reporter.rb

Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,19 @@
11
# frozen_string_literal: true
22

3-
require "erb"
43
require "rubycritic/commands/status_reporter"
5-
require "terminal-table"
64

75
module Skunk
86
module Command
9-
# Knows how to report status for stinky files
7+
# Extends RubyCritic::Command::StatusReporter to silence the status message
108
class StatusReporter < RubyCritic::Command::StatusReporter
119
attr_accessor :analysed_modules
1210

1311
def initialize(options = {})
1412
super(options)
1513
end
1614

17-
HEADINGS = %w[file skunk_score churn_times_cost churn cost coverage].freeze
18-
HEADINGS_WITHOUT_FILE = HEADINGS - %w[file]
19-
HEADINGS_WITHOUT_FILE_WIDTH = HEADINGS_WITHOUT_FILE.size * 17 # padding
20-
21-
TEMPLATE = ERB.new(<<-TEMPL
22-
<%= _ttable %>\n
23-
SkunkScore Total: <%= total_skunk_score %>
24-
Modules Analysed: <%= analysed_modules_count %>
25-
SkunkScore Average: <%= skunk_score_average %>
26-
<% if worst %>Worst SkunkScore: <%= worst.skunk_score %> (<%= worst.pathname %>)<% end %>
27-
28-
Generated with Skunk v<%= Skunk::VERSION %>
29-
TEMPL
30-
)
31-
32-
# Returns a status message with a table of all analysed_modules and
33-
# a skunk score average
3415
def update_status_message
35-
opts = table_options.merge(headings: HEADINGS, rows: table)
36-
37-
_ttable = Terminal::Table.new(opts)
38-
39-
@status_message = TEMPLATE.result(binding)
40-
end
41-
42-
private
43-
44-
def analysed_modules_count
45-
analysed_modules.analysed_modules_count
46-
end
47-
48-
def worst
49-
analysed_modules.worst_module
50-
end
51-
52-
def sorted_modules
53-
analysed_modules.sorted_modules
54-
end
55-
56-
def total_skunk_score
57-
analysed_modules.skunk_score_total
58-
end
59-
60-
def total_churn_times_cost
61-
analysed_modules.total_churn_times_cost
62-
end
63-
64-
def skunk_score_average
65-
analysed_modules.skunk_score_average
66-
end
67-
68-
def table_options
69-
max = sorted_modules.max_by { |a_mod| a_mod.pathname.to_s.length }
70-
width = max.pathname.to_s.length + HEADINGS_WITHOUT_FILE_WIDTH
71-
{
72-
style: {
73-
width: width
74-
}
75-
}
76-
end
77-
78-
def table
79-
sorted_modules.map do |a_mod|
80-
[
81-
a_mod.pathname,
82-
a_mod.skunk_score,
83-
a_mod.churn_times_cost,
84-
a_mod.churn,
85-
a_mod.cost.round(2),
86-
a_mod.coverage.round(2)
87-
]
88-
end
16+
@status_message = ""
8917
end
9018
end
9119
end

lib/skunk/commands/status_sharer.rb

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,16 @@ def base_url
4040

4141
def json_summary
4242
result = {
43-
total_skunk_score: total_skunk_score,
44-
analysed_modules_count: analysed_modules_count,
45-
skunk_score_average: skunk_score_average,
43+
total_skunk_score: analysed_modules.skunk_score_total,
44+
analysed_modules_count: analysed_modules.analysed_modules_count,
45+
skunk_score_average: analysed_modules.skunk_score_average,
4646
skunk_version: Skunk::VERSION
4747
}
4848

49-
if worst
49+
if analysed_modules&.worst_module
50+
worst = analysed_modules.worst_module
5051
result[:worst_skunk_score] = {
51-
file: worst.pathname.to_s,
52+
file: worst.pathname,
5253
skunk_score: worst.skunk_score
5354
}
5455
end
@@ -57,7 +58,7 @@ def json_summary
5758
end
5859

5960
def json_results
60-
sorted_modules.map(&:to_hash)
61+
analysed_modules.sorted_modules.map(&:to_hash)
6162
end
6263

6364
# :reek:UtilityFunction

lib/skunk/config.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module Skunk
44
# Utility module for format validation
55
module FormatValidator
66
# Supported output formats
7-
SUPPORTED_FORMATS = %i[json html].freeze
7+
SUPPORTED_FORMATS = %i[json html console].freeze
88

99
# Check if a format is supported
1010
# @param format [Symbol] Format to check
@@ -24,7 +24,7 @@ def self.supported_formats
2424
# Similar to RubyCritic::Configuration but focused only on Skunk's needs
2525
class Configuration
2626
# Default format
27-
DEFAULT_FORMAT = :json
27+
DEFAULT_FORMAT = :console
2828

2929
def initialize
3030
@formats = [DEFAULT_FORMAT]
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# frozen_string_literal: true
2+
3+
require "erb"
4+
require "terminal-table"
5+
6+
module Skunk
7+
module Generator
8+
module Console
9+
# Generates a console report for the analysed modules.
10+
class Simple
11+
def initialize(analysed_modules)
12+
@analysed_modules = analysed_modules
13+
end
14+
15+
HEADINGS = %w[file skunk_score churn_times_cost churn cost coverage].freeze
16+
HEADINGS_WITHOUT_FILE = HEADINGS - %w[file]
17+
HEADINGS_WITHOUT_FILE_WIDTH = HEADINGS_WITHOUT_FILE.size * 17 # padding
18+
19+
TEMPLATE = ERB.new(<<~TEMPL
20+
<%= _ttable %>
21+
22+
SkunkScore Total: <%= total_skunk_score %>
23+
Modules Analysed: <%= analysed_modules_count %>
24+
SkunkScore Average: <%= skunk_score_average %>
25+
<% if worst %>Worst SkunkScore: <%= worst.skunk_score %> (<%= worst.pathname %>)<% end %>
26+
27+
Generated with Skunk v<%= Skunk::VERSION %>
28+
TEMPL
29+
)
30+
31+
def render
32+
opts = table_options.merge(headings: HEADINGS, rows: table)
33+
_ttable = Terminal::Table.new(opts)
34+
TEMPLATE.result(binding)
35+
end
36+
37+
private
38+
39+
def analysed_modules_count
40+
@analysed_modules.analysed_modules_count
41+
end
42+
43+
def worst
44+
@analysed_modules.worst_module
45+
end
46+
47+
def sorted_modules
48+
@analysed_modules.sorted_modules
49+
end
50+
51+
def total_skunk_score
52+
@analysed_modules.skunk_score_total
53+
end
54+
55+
def total_churn_times_cost
56+
@analysed_modules.total_churn_times_cost
57+
end
58+
59+
def skunk_score_average
60+
@analysed_modules.skunk_score_average
61+
end
62+
63+
def table_options
64+
return { style: { width: 100 } } if sorted_modules.empty?
65+
66+
max = sorted_modules.max_by { |a_mod| a_mod.pathname.to_s.length }
67+
width = max.pathname.to_s.length + HEADINGS_WITHOUT_FILE_WIDTH
68+
{
69+
style: {
70+
width: width
71+
}
72+
}
73+
end
74+
75+
def table
76+
@analysed_modules.files_as_hash.map { |file_hash| self.class.format_hash_row(file_hash) }
77+
end
78+
79+
def self.format_hash_row(file_hash)
80+
[
81+
file_hash[:file],
82+
file_hash[:skunk_score],
83+
file_hash[:churn_times_cost],
84+
file_hash[:churn],
85+
file_hash[:cost],
86+
file_hash[:coverage]
87+
]
88+
end
89+
end
90+
end
91+
end
92+
end

0 commit comments

Comments
 (0)