rubycritic 4.8.0 → 4.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 025aff87e62b4fde94b8920973574ff4231503b8d1ed614705b223c61ab8cf17
4
- data.tar.gz: b3e0521dd5d2859a7535c51a92f5b5bf2666f7cb02ad26a0171e503861ca308c
3
+ metadata.gz: 5e02409fa512f3a1b9449ee32bcaf96a8a0b8de76761252475774fa190ca2059
4
+ data.tar.gz: 928090c08aff3e873916412a2b0ebc947e64495ade84fc60503534e0b531dad4
5
5
  SHA512:
6
- metadata.gz: 6b8d0d03d8d9332e90899854e2f4e76e6b293dbc83e2bd76f0e6991fcce087294364bc2f6a1aceefa1cf101b20e6d94522464c61c1f18f06e3be2bc2c206e992
7
- data.tar.gz: 8103598ab67398b6f5761ff3608e4a60879474f6b9b312700ccc6c48ecc59dc09ec5728d10a654daa11318bdaba316346be0b1360d8193337d68390c7ffa55a8
6
+ metadata.gz: de7584c2a57e92752da20be9a561164234347a7e24d0a8ee036cd54ff213a8f096aec0e7f299f0f534bf260a587314488f26bcdbf61639f47456d276aeebd200
7
+ data.tar.gz: 2988c1a400c24ce70b6468cafb7a70459830d9db42d928e714b552b2cfa6c53baf656d6ed92eea63b89a5a678451bce09e23018481c0992ff9ddbb11b8430e13
data/CHANGELOG.md CHANGED
@@ -1,4 +1,25 @@
1
- # main [(unreleased)](https://github.com/whitesmith/rubycritic/compare/v4.8.0...main)
1
+ # main [(unreleased)](https://github.com/whitesmith/rubycritic/compare/v4.9.0...main)
2
+
3
+ # v4.9.0 / 2023-10-18 [(commits)](https://github.com/whitesmith/rubycritic/compare/v4.8.1...v4.9.0)
4
+
5
+ * [CHANGE] Bump aruba, cucumber, fakefs, flog, mdl, minitest, and rubocop dependencies (by [@faisal][])
6
+ * [CHANGE] Fix test warning related to `cucumber_opts` declaration (by [@faisal][])
7
+ * [BUGFIX] Stop using long-deprecated MiniTest module name, removed in 5.19.0 (by [@faisal][])
8
+ * [CHANGE] Disable VERBOSE warnings in test stubs (by [@fbuys][])
9
+ * [CHANGE] Add rexml dependency for Ruby 3.0.0+ support (by [@fbuys][])
10
+ * [BUGFIX] Raise error when the same branches are compared (by [@rishijain][])
11
+ * [BUGFIX] Churn score was always 0 when rubycritic was executed from a sub-directory (by [@rishijain][])
12
+ * [BUGFIX] Use overview.html as the fallback path when files does not exist during compare option (by [@rishijain][])
13
+ * [BUGFIX] Use name from the file path instead of fetching name from the parser (by [@rishijain][])
14
+
15
+ # v4.8.1 / 2023-05-17 [(commits)](https://github.com/whitesmith/rubycritic/compare/v4.8.0...v4.8.1)
16
+
17
+ * [CHANGE] Update runtime dependencies to current versions of analysis gems (by [@faisal][])
18
+ * [CHANGE] Update the mdl development_dependency from 0.5 to 0.12 (by [@faisal][])
19
+ * [CHANGE] Update rubocop to use current version (~1.51.0) and relevant plugins (by [@faisal][]])
20
+ * [CHANGE] Update testing gems to current versions (by [@faisal][])
21
+ * [BUGFIX] Fix sort and filters on the coverage page (by [@kcamcam][])
22
+ * [CHANGE] Scope churn calculation to provided paths (by [@Fito][])
2
23
 
3
24
  # v4.8.0 / 2023-05-12 [(commits)](https://github.com/whitesmith/rubycritic/compare/v4.7.0...v4.8.0)
4
25
 
@@ -418,4 +439,6 @@
418
439
  [@marcgrimme]: https://github.com/marcgrimme
419
440
  [@katafrakt]: https://github.com/katafrakt
420
441
  [@faisal]: https://github.com/faisal
421
- [@96RadhikaJadhav]: https://github.com/
442
+ [@96RadhikaJadhav]: https://github.com/96RadhikaJadhav
443
+ [@Fito]: https://github.com/Fito
444
+ [@fbuys]: https://github.com/fbuys
data/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/rubycritic.svg)](http://badge.fury.io/rb/rubycritic)
4
4
  [![Continuous Integration](https://github.com/whitesmith/rubycritic/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/whitesmith/rubycritic/actions/workflows/main.yml)
5
- [![Build Status](https://travis-ci.org/whitesmith/rubycritic.svg?branch=master)](https://travis-ci.org/whitesmith/rubycritic)
6
5
  [![Code Climate](https://codeclimate.com/github/whitesmith/rubycritic/badges/gpa.svg)](https://codeclimate.com/github/whitesmith/rubycritic)
7
6
 
8
7
  <img src="https://github.com/whitesmith/rubycritic/raw/main/images/logo.png" alt="RubyCritic Icon" align="right">
@@ -14,9 +13,9 @@ RubyCritic is a gem that wraps around static analysis gems such as [Reek][1], [F
14
13
  - [Overview](#overview)
15
14
  - [Getting Started](#getting-started)
16
15
  - [Usage](#usage)
17
- + [Analyzer Configuration](#analyzer-configuration)
18
- + [Alternative Usage Methods](#alternative-usage-methods)
19
- + [Rake Task](#rake-task)
16
+ + [Analyzer Configuration](#analyzer-configuration)
17
+ + [Alternative Usage Methods](#alternative-usage-methods)
18
+ + [Rake Task](#rake-task)
20
19
  - [Formatters](#formatters)
21
20
  - [Compatibility](#compatibility)
22
21
  - [Improving RubyCritic](#improving-rubyCritic)
@@ -95,7 +94,8 @@ current directory:
95
94
  $ rubycritic
96
95
  ```
97
96
 
98
- Alternatively you can pass `rubycritic` a list of files and directories to check:
97
+ Alternatively you can pass `rubycritic` a list of files and directories.
98
+ The analysis will be scoped to the provided files and directories:
99
99
 
100
100
  ```bash
101
101
  $ rubycritic app lib/foo.rb
@@ -147,7 +147,7 @@ no_browser: true # default is false
147
147
  formats: # Available values are: html, json, console, lint. Default value is html.
148
148
  - console
149
149
  minimum_score: 95 # default is 0
150
- paths: # Files to analyse.
150
+ paths: # Files to analyse. Churn calculation is scoped to these files when using Git SCM.
151
151
  - 'app/controllers/'
152
152
  - 'app/models/'
153
153
  ```
@@ -159,9 +159,9 @@ paths: # Files to analyse.
159
159
  project root and `RubyCritic` will respect this configuration.
160
160
  * [`flay`](https://github.com/seattlerb/flay): We use `flay`'s default configuration.
161
161
  * [`flog`](https://github.com/seattlerb/flog): We use `flog`'s default configuration with a couple of [smaller tweaks](https://github.com/whitesmith/rubycritic/blob/main/lib/rubycritic/analysers/helpers/flog.rb#L5):
162
- * `all`: Forces `flog` to report scores on all classes and methods. Without this option `flog` will only give results up to a certain threshold.
163
- * `continue`: Makes it so that `flog` does not abort when a ruby file cannot be parsed.
164
- * `methods`: Configures `flog` to skip code outside of methods. It prevents `flog` from reporting on the "methods" `private` and `protected`. It also prevents `flog` from reporting on Rails methods like `before_action` and `has_many`.
162
+ * `all`: Forces `flog` to report scores on all classes and methods. Without this option `flog` will only give results up to a certain threshold.
163
+ * `continue`: Makes it so that `flog` does not abort when a ruby file cannot be parsed.
164
+ * `methods`: Configures `flog` to skip code outside of methods. It prevents `flog` from reporting on the "methods" `private` and `protected`. It also prevents `flog` from reporting on Rails methods like `before_action` and `has_many`.
165
165
 
166
166
  ### Alternative Usage Methods
167
167
 
@@ -235,7 +235,7 @@ See [formatters](docs/formatters.md)
235
235
  RubyCritic is supporting Ruby versions:
236
236
 
237
237
  | Ruby version | Latest RubyCritic version |
238
- | - | - |
238
+ | --- | --- |
239
239
  | 2.4 | [v4.7.0](https://github.com/whitesmith/rubycritic/tree/v4.7.0) |
240
240
  | 2.5 | [v4.7.0](https://github.com/whitesmith/rubycritic/tree/v4.7.0) |
241
241
  | 2.6 | [v4.7.0](https://github.com/whitesmith/rubycritic/tree/v4.7.0) |
data/ROADMAP.md CHANGED
@@ -6,9 +6,9 @@ These are more nice-to-haves than promises. We can always dream. But this is wha
6
6
 
7
7
  - [ ] Improve how modules are graded. Each module is awarded a score, depending on:
8
8
 
9
- * Its complexity, based off of this [post by Jake Scruggs](http://jakescruggs.blogspot.pt/2008/08/whats-good-flog-score.html), creator of the MetricFu gem. For every 25 points of complexity (as calculated by Flog), the score increases by 1.
9
+ * Its complexity, based off of this [post by Jake Scruggs](http://jakescruggs.blogspot.pt/2008/08/whats-good-flog-score.html), creator of the MetricFu gem. For every 25 points of complexity (as calculated by Flog), the score increases by 1.
10
10
 
11
- * Its duplication mass, based off of observations of a few Code Climate repos. For every 25 points of mass (as calculated by Flay), the score increases by 1.
11
+ * Its duplication mass, based off of observations of a few Code Climate repos. For every 25 points of mass (as calculated by Flay), the score increases by 1.
12
12
 
13
13
  Finally, this score is translated to a grade like [this](https://github.com/whitesmith/rubycritic/blob/43005e7b76dd0c648c7715133e42afdd6ea9a065/lib/rubycritic/core/rating.rb), based off of a [Code Climate blog post](http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/#value-objects).
14
14
 
@@ -21,36 +21,36 @@ These are more nice-to-haves than promises. We can always dream. But this is wha
21
21
  - [ ] Make the gem configurable using a dotfile like .rubycritic.yml. #30
22
22
  Here are some possible settings:
23
23
 
24
- - [ ] Quiet mode. As of right now, any Ruby code that is unparsable will be reported three times (one time by Flog, another by Flay and another by Reek). Only Flog implements a quiet option, which means we have to implement that quiet option on Flay and on Reek before we can add it to RubyCritic. Or we could just do `$stderr = StringIO.new`... I wonder if that's really really smart or really really stupid.
24
+ - [ ] Quiet mode. As of right now, any Ruby code that is unparsable will be reported three times (one time by Flog, another by Flay and another by Reek). Only Flog implements a quiet option, which means we have to implement that quiet option on Flay and on Reek before we can add it to RubyCritic. Or we could just do `$stderr = StringIO.new`... I wonder if that's really really smart or really really stupid.
25
25
 
26
- - [ ] Verbose mode. #61
26
+ - [ ] Verbose mode. #61
27
27
 
28
- - [ ] Ignoring/excluding files. #11
28
+ - [ ] Ignoring/excluding files. #11
29
29
 
30
- - [ ] Allow configuring date range of Churn calculation. #37 Right now, they are limited to the last year. #39
30
+ - [ ] Allow configuring date range of Churn calculation. #37 Right now, they are limited to the last year. #39
31
31
 
32
32
  - [ ] Highlight blocks of duplicated code instead of just the start of the block. This will probably require rewriting Flay with [parser](https://github.com/whitequark/parser) instead of ruby_parser.
33
33
 
34
34
  - [ ] Integrate other gems, like:
35
35
 
36
- - [x] [Simplecov](https://github.com/colszowka/simplecov) to provide code coverage. #319
36
+ - [x] [Simplecov](https://github.com/colszowka/simplecov) to provide code coverage. #319
37
37
 
38
- - [ ] [Rubocop](https://github.com/bbatsov/rubocop/) to provide style issues
38
+ - [ ] [Rubocop](https://github.com/bbatsov/rubocop/) to provide style issues
39
39
 
40
- - [ ] [Brakeman](https://github.com/presidentbeef/brakeman) to provide security issues (Rails-only feature)
40
+ - [ ] [Brakeman](https://github.com/presidentbeef/brakeman) to provide security issues (Rails-only feature)
41
41
 
42
- - [ ] [Rails Best Practices](https://github.com/railsbp/rails_best_practices) to provide Rails smells (Rails-only feature) #14
42
+ - [ ] [Rails Best Practices](https://github.com/railsbp/rails_best_practices) to provide Rails smells (Rails-only feature) #14
43
43
 
44
- - [ ] [SandiMeter](https://github.com/makaroni4/sandi_meter) #15
44
+ - [ ] [SandiMeter](https://github.com/makaroni4/sandi_meter) #15
45
45
 
46
46
  - [ ] Improve UI.
47
47
 
48
- - [ ] Make it beautiful.
48
+ - [ ] Make it beautiful.
49
49
 
50
- - [ ] Figure out where the "suggestions to fix code smells" should be presented.
50
+ - [ ] Figure out where the "suggestions to fix code smells" should be presented.
51
51
 
52
- - [ ] Create some kind of toggle option between various types of issues. Just like we can toggle between "Smells" and "Coverage" in Code Climate:
52
+ - [ ] Create some kind of toggle option between various types of issues. Just like we can toggle between "Smells" and "Coverage" in Code Climate:
53
53
 
54
- ![Code Climate Toggle Option](https://camo.githubusercontent.com/d97fc62dae6ebef1f35bda91942d4a6bacc445b2/687474703a2f2f626c6f672e636f6465636c696d6174652e636f6d2f696d616765732f706f7374732f74657374696e672e676966)
54
+ ![Code Climate Toggle Option](https://camo.githubusercontent.com/d97fc62dae6ebef1f35bda91942d4a6bacc445b2/687474703a2f2f626c6f672e636f6465636c696d6174652e636f6d2f696d616765732f706f7374732f74657374696e672e676966)
55
55
 
56
- Having an option to toggle between "Smells", "Security" (Brakeman) and "Style" (Rubocop) would be great. But that's already assuming we can integrate those gems into RubyCritic.
56
+ Having an option to toggle between "Smells", "Security" (Brakeman) and "Style" (Rubocop) would be great. But that's already assuming we can integrate those gems into RubyCritic.
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ Rake::TestTask.new do |task|
14
14
  end
15
15
 
16
16
  Cucumber::Rake::Task.new(:features) do |t|
17
- t.cucumber_opts = 'features --format progress --color'
17
+ t.cucumber_opts = %w[features --format progress --color]
18
18
  end
19
19
 
20
20
  RuboCop::RakeTask.new
@@ -13,12 +13,12 @@ module Parser
13
13
  count
14
14
  end
15
15
 
16
- def recursive_children
16
+ def recursive_children(&block)
17
17
  children.each do |child|
18
18
  next unless child.is_a?(Parser::AST::Node)
19
19
 
20
20
  yield child
21
- child.recursive_children { |grand_child| yield grand_child }
21
+ child.recursive_children(&block)
22
22
  end
23
23
  end
24
24
 
@@ -9,7 +9,7 @@ module RubyCritic
9
9
  end
10
10
 
11
11
  def first_name
12
- names.first
12
+ name_from_path.first
13
13
  end
14
14
 
15
15
  def names
@@ -77,8 +77,9 @@ module RubyCritic
77
77
 
78
78
  def formats
79
79
  formats = Array(options['formats'])
80
+ formats_to_check = %w[html json console lint]
80
81
  formats.select do |format|
81
- %w[html json console lint].include?(format)
82
+ formats_to_check.include?(format)
82
83
  end.map(&:to_sym)
83
84
  end
84
85
 
@@ -18,6 +18,10 @@ module RubyCritic
18
18
  end
19
19
 
20
20
  def execute
21
+ if Config.send(:base_branch) == Config.send(:feature_branch)
22
+ raise('The branch you are on and are comparing with are the same.
23
+ Please switch to a different branch or choose a different branch to compare.')
24
+ end
21
25
  compare_branches
22
26
  status_reporter.score = Config.feature_branch_score
23
27
  status_reporter
@@ -91,9 +95,9 @@ module RubyCritic
91
95
 
92
96
  # create a txt file with the branch score details
93
97
  def build_details
94
- details = "Base branch (#{Config.base_branch}) score: #{Config.base_branch_score} \n"\
98
+ details = "Base branch (#{Config.base_branch}) score: #{Config.base_branch_score} \n" \
95
99
  "Feature branch (#{Config.feature_branch}) score: #{Config.feature_branch_score} \n"
96
- File.open("#{Config.compare_root_directory}/build_details.txt", 'w') { |file| file.write(details) }
100
+ File.write("#{Config.compare_root_directory}/build_details.txt", details)
97
101
  end
98
102
 
99
103
  # store the analysed moduled collection based on the branch
@@ -4,6 +4,7 @@ module RubyCritic
4
4
  module Command
5
5
  class StatusReporter
6
6
  attr_reader :status, :status_message, :score
7
+
7
8
  SUCCESS = 0
8
9
  SCORE_BELOW_MINIMUM = 1
9
10
 
@@ -7,6 +7,7 @@ module RubyCritic
7
7
  module Command
8
8
  class Version < Base
9
9
  attr_reader :status_reporter
10
+
10
11
  def execute
11
12
  puts "RubyCritic #{VERSION}"
12
13
  status_reporter
@@ -10,7 +10,7 @@ module RubyCritic
10
10
  :feature_branch, :base_branch_score, :feature_branch_score,
11
11
  :base_root_directory, :feature_root_directory,
12
12
  :compare_root_directory, :threshold_score, :base_branch_collection,
13
- :feature_branch_collection, :churn_after, :ruby_extensions
13
+ :feature_branch_collection, :churn_after, :ruby_extensions, :paths
14
14
 
15
15
  def set(options)
16
16
  self.mode = options[:mode] || :default
@@ -20,11 +20,16 @@ module RubyCritic
20
20
  self.open_with = options[:open_with]
21
21
  self.no_browser = options[:no_browser]
22
22
  self.threshold_score = options[:threshold_score].to_i
23
- self.ruby_extensions = options[:ruby_extensions] || %w[.rb .rake .thor]
23
+ setup_analysis_targets(options)
24
24
  setup_version_control(options)
25
25
  setup_formats(options)
26
26
  end
27
27
 
28
+ def setup_analysis_targets(options)
29
+ self.paths = options[:paths] || ['.']
30
+ self.ruby_extensions = options[:ruby_extensions] || %w[.rb .rake .thor]
31
+ end
32
+
28
33
  def setup_version_control(options)
29
34
  self.base_branch = options[:base_branch]
30
35
  self.feature_branch = options[:feature_branch]
@@ -41,7 +41,7 @@ module RubyCritic
41
41
  end
42
42
 
43
43
  def cost
44
- @cost ||= smells.map(&:cost).inject(0.0, :+) +
44
+ @cost ||= smells.sum(0.0, &:cost) +
45
45
  (complexity / COMPLEXITY_FACTOR)
46
46
  end
47
47
 
@@ -46,7 +46,7 @@ module RubyCritic
46
46
 
47
47
  def score
48
48
  if @modules.any?
49
- (MAX_SCORE - average_limited_cost * COST_MULTIPLIER).round(2)
49
+ (MAX_SCORE - (average_limited_cost * COST_MULTIPLIER)).round(2)
50
50
  else
51
51
  0.0
52
52
  end
@@ -69,7 +69,7 @@ module RubyCritic
69
69
  def average_cost
70
70
  num_modules = @modules.size
71
71
  if num_modules.positive?
72
- map { |mod| limited_cost_for(mod) }.reduce(:+) / num_modules.to_f
72
+ sum { |mod| limited_cost_for(mod) } / num_modules.to_f
73
73
  else
74
74
  0.0
75
75
  end
@@ -7,7 +7,8 @@ module RubyCritic
7
7
  elsif cost <= 4 then new('B')
8
8
  elsif cost <= 8 then new('C')
9
9
  elsif cost <= 16 then new('D')
10
- else new('F')
10
+ else
11
+ new('F')
11
12
  end
12
13
  end
13
14
 
@@ -20,7 +20,7 @@ module RubyCritic
20
20
  FLOG_DOCS_URL = 'http://docs.seattlerb.org/flog/'.freeze
21
21
 
22
22
  def at_location?(other_location)
23
- locations.any? { |location| location == other_location }
23
+ locations.any?(other_location)
24
24
  end
25
25
 
26
26
  def multiple_locations?
@@ -239,11 +239,16 @@ $("#codeTable")
239
239
  sortList: [[0,1]]
240
240
  });
241
241
 
242
- $("#js-index-table")
242
+ $("#smellsTable")
243
243
  .tablesorter({ // Sort the table
244
244
  sortList: [[0,0]]
245
245
  });
246
246
 
247
+ $("#coverageTable")
248
+ .tablesorter({ // Sort the table
249
+ sortList: [[0,1]]
250
+ });
251
+
247
252
  $(".js-timeago").timeago();
248
253
 
249
254
  $(function(){
@@ -277,5 +282,6 @@ $(document).ready(function(){
277
282
 
278
283
  var initTableFilters = function() {
279
284
  $("#codeTable").filterTable({ignoreColumns: [2], placeholder: 'Filter by Name'});
280
- $("#js-index-table").filterTable({ignoreColumns: [2, 3, 4, 5], placeholder: 'Filter by Smell or Location', inputSelector: 'form-control'});
285
+ $("#smellsTable").filterTable({ignoreColumns: [2, 3, 4, 5], placeholder: 'Filter by Smell or Location', inputSelector: 'form-control'});
286
+ $("#coverageTable").filterTable({ignoreColumns: [0], placeholder: 'Filter by Smell or Location', inputSelector: 'form-control'});
281
287
  }
@@ -19,7 +19,7 @@ module RubyCritic
19
19
  end
20
20
 
21
21
  def render
22
- template.result(binding).delete("\n") + "\n"
22
+ "#{template.result(binding).delete("\n")}\n"
23
23
  end
24
24
 
25
25
  private
@@ -8,7 +8,7 @@
8
8
  </div>
9
9
  <!--End Page Title -->
10
10
  <div class="Content_Wrapper">
11
- <table id="js-index-table" class="table coverage-index-table index-table sortable-table">
11
+ <table id="coverageTable" class="table index-table sortable-table tablesorter">
12
12
  <thead>
13
13
  <tr>
14
14
  <% unless Config.suppress_ratings %>
@@ -20,20 +20,23 @@
20
20
  </thead>
21
21
  <% @analysed_modules.each do |analysed_module| %>
22
22
  <tr>
23
- <tr>
24
- <% unless Config.suppress_ratings %>
25
- <td>
26
- <div class="rating <%= analysed_module.coverage_rating.to_s.downcase %>"><%= analysed_module.coverage_rating %></div>
27
- </td>
28
- <% end %>
23
+ <% unless Config.suppress_ratings %>
29
24
  <td>
30
- <ul class="nav nav-pills">
31
- <li role="presentation" >
32
- <a href="<%= file_path(analysed_module.pathname.sub_ext('.html')) %>"><%= analysed_module.name %></a>
33
- </li>
34
- </ul>
25
+ <div class="rating <%= analysed_module.coverage_rating.to_s.downcase %>">
26
+ <%= analysed_module.coverage_rating %>
27
+ </div>
35
28
  </td>
36
- <td><%= '%g' % analysed_module.coverage %>%</td>
29
+ <% end %>
30
+ <td>
31
+ <ul class="nav nav-pills">
32
+ <li role="presentation" >
33
+ <a href="<%= file_path(analysed_module.pathname.sub_ext('.html')) %>">
34
+ <%= analysed_module.name %>
35
+ </a>
36
+ </li>
37
+ </ul>
38
+ </td>
39
+ <td><%= '%.2f' % analysed_module.coverage %>%</td>
37
40
  </tr>
38
41
  <% end %>
39
42
  </table>
@@ -8,7 +8,7 @@
8
8
  </div>
9
9
  <!--End Page Title -->
10
10
  <div class="Content_Wrapper">
11
- <table id="js-index-table" class="table smells-index-table index-table sortable-table">
11
+ <table id="smellsTable" class="table smells-index-table index-table sortable-table">
12
12
  <thead>
13
13
  <tr>
14
14
  <th width="30%" class="table-header">Smell<span class="sort-type"></span></th>
@@ -24,7 +24,10 @@ module RubyCritic
24
24
  end
25
25
 
26
26
  def code_index_path(root_directory, file_name)
27
- file_path("#{File.expand_path(root_directory)}/#{file_name}")
27
+ root_directory_path = File.expand_path(root_directory)
28
+ index_path = "#{root_directory_path}/#{file_name}"
29
+ index_path = "#{root_directory_path}/overview.html" unless File.exist?(index_path)
30
+ file_path(index_path)
28
31
  end
29
32
 
30
33
  private
@@ -33,9 +33,7 @@ module RubyCritic
33
33
  def create_directories_and_files
34
34
  Array(generators).each do |generator|
35
35
  FileUtils.mkdir_p(generator.file_directory)
36
- File.open(generator.file_pathname, 'w+') do |file|
37
- file.write(generator.render)
38
- end
36
+ File.write(generator.file_pathname, generator.render)
39
37
  end
40
38
  end
41
39
 
@@ -11,9 +11,7 @@ module RubyCritic
11
11
 
12
12
  def generate_report
13
13
  FileUtils.mkdir_p(generator.file_directory)
14
- File.open(generator.file_pathname, 'w+') do |file|
15
- file.write(generator.render)
16
- end
14
+ File.write(generator.file_pathname, generator.render)
17
15
  end
18
16
 
19
17
  private
@@ -11,9 +11,7 @@ module RubyCritic
11
11
 
12
12
  def generate_report
13
13
  FileUtils.mkdir_p(generator.file_directory)
14
- File.open(generator.file_pathname, 'w+') do |file|
15
- file.write(reports.join("\n"))
16
- end
14
+ File.write(generator.file_pathname, reports.join("\n"))
17
15
  end
18
16
 
19
17
  def generator
@@ -21,9 +21,9 @@ module RubyCritic
21
21
  if supported_system
22
22
  supported_system.new
23
23
  else
24
- puts 'RubyCritic can provide more feedback if you use '\
25
- "a #{connected_system_names} repository. "\
26
- 'Churn will not be calculated.'
24
+ puts 'RubyCritic can provide more feedback if you use ' \
25
+ "a #{connected_system_names} repository. " \
26
+ 'Churn will not be calculated.'
27
27
  Double.new
28
28
  end
29
29
  end
@@ -21,11 +21,11 @@ module RubyCritic
21
21
  end
22
22
 
23
23
  class Churn
24
- def initialize(churn_after: nil)
25
- @renames = Renames.new
24
+ def initialize(churn_after: nil, paths: ['.'])
25
+ @churn_after = churn_after
26
+ @paths = Array(paths)
26
27
  @date = nil
27
28
  @stats = {}
28
- @churn_after = churn_after
29
29
 
30
30
  call
31
31
  end
@@ -41,16 +41,27 @@ module RubyCritic
41
41
  private
42
42
 
43
43
  def call
44
+ git_log_commands.each { |log_command| exec_git_command(log_command) }
45
+ end
46
+
47
+ def exec_git_command(command)
44
48
  Git
45
- .git(git_log_command)
49
+ .git(command)
46
50
  .split("\n")
47
51
  .reject(&:empty?)
48
52
  .each { |line| process_line(line) }
49
53
  end
50
54
 
51
- def git_log_command
52
- after_clause = @churn_after ? "--after='#{@churn_after}' " : ''
53
- "log --all --date=iso --follow --format='format:date:%x09%ad' --name-status #{after_clause}."
55
+ def git_log_commands
56
+ @paths.map { |path| git_log_command(path) }
57
+ end
58
+
59
+ def git_log_command(path)
60
+ "log --all --date=iso --follow --format='format:date:%x09%ad' --name-status #{after_clause}#{path}"
61
+ end
62
+
63
+ def after_clause
64
+ @churn_after ? "--after='#{@churn_after}' " : ''
54
65
  end
55
66
 
56
67
  def process_line(line)
@@ -62,6 +73,7 @@ module RubyCritic
62
73
  when /^[RC]/
63
74
  process_rename(*rest)
64
75
  else
76
+ rest = filename_for_subdirectory(rest[0])
65
77
  process_file(*rest)
66
78
  end
67
79
  end
@@ -71,12 +83,21 @@ module RubyCritic
71
83
  end
72
84
 
73
85
  def process_rename(from, to)
74
- @renames.renamed(from, to)
86
+ renames.renamed(from, to)
75
87
  process_file(to)
76
88
  end
77
89
 
90
+ def filename_for_subdirectory(filename)
91
+ git_path = Git.git('rev-parse --show-toplevel')
92
+ cd_path = Dir.pwd
93
+ if cd_path.length > git_path.length
94
+ filename = filename.sub(/^#{Regexp.escape("#{File.basename(cd_path)}/")}/, '')
95
+ end
96
+ [filename]
97
+ end
98
+
78
99
  def process_file(filename)
79
- record_commit(@renames.current(filename), @date)
100
+ record_commit(renames.current(filename), @date)
80
101
  end
81
102
 
82
103
  def record_commit(filename, date)
@@ -84,6 +105,10 @@ module RubyCritic
84
105
  stats.count += 1
85
106
  end
86
107
 
108
+ def renames
109
+ @renames ||= Renames.new
110
+ end
111
+
87
112
  def stats(path)
88
113
  @stats.fetch(path, Stats.new(0))
89
114
  end
@@ -30,7 +30,7 @@ module RubyCritic
30
30
  end
31
31
 
32
32
  def churn
33
- @churn ||= Churn.new(churn_after: Config.churn_after)
33
+ @churn ||= Churn.new(churn_after: Config.churn_after, paths: Config.paths)
34
34
  end
35
35
 
36
36
  def revisions_count(path)
@@ -71,18 +71,18 @@ module RubyCritic
71
71
 
72
72
  def self.modified_files
73
73
  modified_files = `git diff --name-status #{Config.base_branch} #{Config.feature_branch}`
74
- modified_files.split("\n").map do |line|
74
+ modified_files.split("\n").filter_map do |line|
75
75
  next if line.start_with?('D')
76
76
 
77
77
  file_name = line.split("\t")[1]
78
78
  file_name
79
- end.compact
79
+ end
80
80
  end
81
81
 
82
82
  def self.current_branch
83
83
  branch_list = `git branch`
84
84
  branch = branch_list.match(/\*.*$/)[0].gsub('* ', '')
85
- branch = branch.gsub(/\(HEAD detached at (.*)\)$/, '\1') if branch =~ /\(HEAD detached at (.*)\)$/
85
+ branch = branch.gsub(/\(HEAD detached at (.*)\)$/, '\1') if /\(HEAD detached at (.*)\)$/.match?(branch)
86
86
  branch
87
87
  end
88
88
 
@@ -88,7 +88,7 @@ module RubyCritic
88
88
  end
89
89
 
90
90
  def self.compute_cache_lines(lines)
91
- perforce_lines = Hash[*lines.map { |line| line.split[1..-1] }.flatten]
91
+ perforce_lines = Hash[*lines.map { |line| line.split[1..] }.flatten]
92
92
  PerforceStats.new(
93
93
  Perforce.normalized_file_path(perforce_lines['clientFile']),
94
94
  perforce_lines['headRev'],
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyCritic
4
- VERSION = '4.8.0'.freeze
4
+ VERSION = '4.9.0'.freeze
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubycritic
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.8.0
4
+ version: 4.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guilherme Simoes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-12 00:00:00.000000000 Z
11
+ date: 2023-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: flay
@@ -16,70 +16,70 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.8'
19
+ version: '2.13'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.8'
26
+ version: '2.13'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: flog
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '4.4'
33
+ version: '4.7'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '4.4'
40
+ version: '4.7'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: launchy
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 2.0.0
47
+ version: 2.5.2
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 2.0.0
54
+ version: 2.5.2
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: parser
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 2.6.0
61
+ version: 3.2.2.1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 2.6.0
68
+ version: 3.2.2.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rainbow
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '3.0'
75
+ version: 3.1.1
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '3.0'
82
+ version: 3.1.1
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: reek
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -100,103 +100,94 @@ dependencies:
100
100
  - - "<"
101
101
  - !ruby/object:Gem::Version
102
102
  version: '7.0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rexml
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
103
117
  - !ruby/object:Gem::Dependency
104
118
  name: ruby_parser
105
119
  requirement: !ruby/object:Gem::Requirement
106
120
  requirements:
107
121
  - - "~>"
108
122
  - !ruby/object:Gem::Version
109
- version: '3.8'
123
+ version: '3.20'
110
124
  type: :runtime
111
125
  prerelease: false
112
126
  version_requirements: !ruby/object:Gem::Requirement
113
127
  requirements:
114
128
  - - "~>"
115
129
  - !ruby/object:Gem::Version
116
- version: '3.8'
130
+ version: '3.20'
117
131
  - !ruby/object:Gem::Dependency
118
132
  name: simplecov
119
133
  requirement: !ruby/object:Gem::Requirement
120
134
  requirements:
121
135
  - - ">="
122
136
  - !ruby/object:Gem::Version
123
- version: 0.17.0
137
+ version: 0.22.0
124
138
  type: :runtime
125
139
  prerelease: false
126
140
  version_requirements: !ruby/object:Gem::Requirement
127
141
  requirements:
128
142
  - - ">="
129
143
  - !ruby/object:Gem::Version
130
- version: 0.17.0
144
+ version: 0.22.0
131
145
  - !ruby/object:Gem::Dependency
132
146
  name: tty-which
133
147
  requirement: !ruby/object:Gem::Requirement
134
148
  requirements:
135
149
  - - "~>"
136
150
  - !ruby/object:Gem::Version
137
- version: 0.4.0
151
+ version: 0.5.0
138
152
  type: :runtime
139
153
  prerelease: false
140
154
  version_requirements: !ruby/object:Gem::Requirement
141
155
  requirements:
142
156
  - - "~>"
143
157
  - !ruby/object:Gem::Version
144
- version: 0.4.0
158
+ version: 0.5.0
145
159
  - !ruby/object:Gem::Dependency
146
160
  name: virtus
147
161
  requirement: !ruby/object:Gem::Requirement
148
162
  requirements:
149
163
  - - "~>"
150
164
  - !ruby/object:Gem::Version
151
- version: '1.0'
165
+ version: '2.0'
152
166
  type: :runtime
153
167
  prerelease: false
154
168
  version_requirements: !ruby/object:Gem::Requirement
155
169
  requirements:
156
170
  - - "~>"
157
171
  - !ruby/object:Gem::Version
158
- version: '1.0'
159
- - !ruby/object:Gem::Dependency
160
- name: appraisal
161
- requirement: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - ">="
164
- - !ruby/object:Gem::Version
165
- version: '0'
166
- type: :development
167
- prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- requirements:
170
- - - ">="
171
- - !ruby/object:Gem::Version
172
- version: '0'
172
+ version: '2.0'
173
173
  - !ruby/object:Gem::Dependency
174
174
  name: aruba
175
175
  requirement: !ruby/object:Gem::Requirement
176
176
  requirements:
177
177
  - - "~>"
178
178
  - !ruby/object:Gem::Version
179
- version: '0.12'
180
- - - ">="
181
- - !ruby/object:Gem::Version
182
- version: 0.12.0
179
+ version: 2.2.0
183
180
  type: :development
184
181
  prerelease: false
185
182
  version_requirements: !ruby/object:Gem::Requirement
186
183
  requirements:
187
184
  - - "~>"
188
185
  - !ruby/object:Gem::Version
189
- version: '0.12'
190
- - - ">="
191
- - !ruby/object:Gem::Version
192
- version: 0.12.0
186
+ version: 2.2.0
193
187
  - !ruby/object:Gem::Dependency
194
188
  name: bundler
195
189
  requirement: !ruby/object:Gem::Requirement
196
190
  requirements:
197
- - - "~>"
198
- - !ruby/object:Gem::Version
199
- version: '2.0'
200
191
  - - ">="
201
192
  - !ruby/object:Gem::Version
202
193
  version: 2.0.0
@@ -204,9 +195,6 @@ dependencies:
204
195
  prerelease: false
205
196
  version_requirements: !ruby/object:Gem::Requirement
206
197
  requirements:
207
- - - "~>"
208
- - !ruby/object:Gem::Version
209
- version: '2.0'
210
198
  - - ">="
211
199
  - !ruby/object:Gem::Version
212
200
  version: 2.0.0
@@ -236,20 +224,20 @@ dependencies:
236
224
  requirements:
237
225
  - - "~>"
238
226
  - !ruby/object:Gem::Version
239
- version: '3.0'
240
- - - ">="
227
+ version: 9.0.2
228
+ - - "!="
241
229
  - !ruby/object:Gem::Version
242
- version: 2.2.0
230
+ version: 9.0.0
243
231
  type: :development
244
232
  prerelease: false
245
233
  version_requirements: !ruby/object:Gem::Requirement
246
234
  requirements:
247
235
  - - "~>"
248
236
  - !ruby/object:Gem::Version
249
- version: '3.0'
250
- - - ">="
237
+ version: 9.0.2
238
+ - - "!="
251
239
  - !ruby/object:Gem::Version
252
- version: 2.2.0
240
+ version: 9.0.0
253
241
  - !ruby/object:Gem::Dependency
254
242
  name: diff-lcs
255
243
  requirement: !ruby/object:Gem::Requirement
@@ -270,38 +258,41 @@ dependencies:
270
258
  requirements:
271
259
  - - "~>"
272
260
  - !ruby/object:Gem::Version
273
- version: 1.4.1
274
- - - "<"
275
- - !ruby/object:Gem::Version
276
- version: 2.0.0
261
+ version: 2.5.0
277
262
  type: :development
278
263
  prerelease: false
279
264
  version_requirements: !ruby/object:Gem::Requirement
280
265
  requirements:
281
266
  - - "~>"
282
267
  - !ruby/object:Gem::Version
283
- version: 1.4.1
284
- - - "<"
285
- - !ruby/object:Gem::Version
286
- version: 2.0.0
268
+ version: 2.5.0
287
269
  - !ruby/object:Gem::Dependency
288
270
  name: mdl
289
271
  requirement: !ruby/object:Gem::Requirement
290
272
  requirements:
291
273
  - - "~>"
292
274
  - !ruby/object:Gem::Version
293
- version: 0.5.0
275
+ version: 0.13.0
276
+ - - ">="
277
+ - !ruby/object:Gem::Version
278
+ version: 0.12.0
294
279
  type: :development
295
280
  prerelease: false
296
281
  version_requirements: !ruby/object:Gem::Requirement
297
282
  requirements:
298
283
  - - "~>"
299
284
  - !ruby/object:Gem::Version
300
- version: 0.5.0
285
+ version: 0.13.0
286
+ - - ">="
287
+ - !ruby/object:Gem::Version
288
+ version: 0.12.0
301
289
  - !ruby/object:Gem::Dependency
302
290
  name: minitest
303
291
  requirement: !ruby/object:Gem::Requirement
304
292
  requirements:
293
+ - - "~>"
294
+ - !ruby/object:Gem::Version
295
+ version: 5.20.0
305
296
  - - ">="
306
297
  - !ruby/object:Gem::Version
307
298
  version: 5.3.0
@@ -309,6 +300,9 @@ dependencies:
309
300
  prerelease: false
310
301
  version_requirements: !ruby/object:Gem::Requirement
311
302
  requirements:
303
+ - - "~>"
304
+ - !ruby/object:Gem::Version
305
+ version: 5.20.0
312
306
  - - ">="
313
307
  - !ruby/object:Gem::Version
314
308
  version: 5.3.0
@@ -338,27 +332,21 @@ dependencies:
338
332
  requirements:
339
333
  - - "~>"
340
334
  - !ruby/object:Gem::Version
341
- version: '1.1'
342
- - - ">="
343
- - !ruby/object:Gem::Version
344
- version: 1.1.0
335
+ version: 2.1.0
345
336
  type: :development
346
337
  prerelease: false
347
338
  version_requirements: !ruby/object:Gem::Requirement
348
339
  requirements:
349
340
  - - "~>"
350
341
  - !ruby/object:Gem::Version
351
- version: '1.1'
352
- - - ">="
353
- - !ruby/object:Gem::Version
354
- version: 1.1.0
342
+ version: 2.1.0
355
343
  - !ruby/object:Gem::Dependency
356
344
  name: rake
357
345
  requirement: !ruby/object:Gem::Requirement
358
346
  requirements:
359
347
  - - "~>"
360
348
  - !ruby/object:Gem::Version
361
- version: '12.0'
349
+ version: 13.0.6
362
350
  - - ">="
363
351
  - !ruby/object:Gem::Version
364
352
  version: 11.0.0
@@ -368,7 +356,7 @@ dependencies:
368
356
  requirements:
369
357
  - - "~>"
370
358
  - !ruby/object:Gem::Version
371
- version: '12.0'
359
+ version: 13.0.6
372
360
  - - ">="
373
361
  - !ruby/object:Gem::Version
374
362
  version: 11.0.0
@@ -392,14 +380,62 @@ dependencies:
392
380
  requirements:
393
381
  - - "~>"
394
382
  - !ruby/object:Gem::Version
395
- version: 0.75.0
383
+ version: 1.57.1
384
+ - - ">="
385
+ - !ruby/object:Gem::Version
386
+ version: 1.54.0
396
387
  type: :development
397
388
  prerelease: false
398
389
  version_requirements: !ruby/object:Gem::Requirement
399
390
  requirements:
400
391
  - - "~>"
401
392
  - !ruby/object:Gem::Version
402
- version: 0.75.0
393
+ version: 1.57.1
394
+ - - ">="
395
+ - !ruby/object:Gem::Version
396
+ version: 1.54.0
397
+ - !ruby/object:Gem::Dependency
398
+ name: rubocop-minitest
399
+ requirement: !ruby/object:Gem::Requirement
400
+ requirements:
401
+ - - ">="
402
+ - !ruby/object:Gem::Version
403
+ version: '0'
404
+ type: :development
405
+ prerelease: false
406
+ version_requirements: !ruby/object:Gem::Requirement
407
+ requirements:
408
+ - - ">="
409
+ - !ruby/object:Gem::Version
410
+ version: '0'
411
+ - !ruby/object:Gem::Dependency
412
+ name: rubocop-performance
413
+ requirement: !ruby/object:Gem::Requirement
414
+ requirements:
415
+ - - ">="
416
+ - !ruby/object:Gem::Version
417
+ version: '0'
418
+ type: :development
419
+ prerelease: false
420
+ version_requirements: !ruby/object:Gem::Requirement
421
+ requirements:
422
+ - - ">="
423
+ - !ruby/object:Gem::Version
424
+ version: '0'
425
+ - !ruby/object:Gem::Dependency
426
+ name: rubocop-rake
427
+ requirement: !ruby/object:Gem::Requirement
428
+ requirements:
429
+ - - ">="
430
+ - !ruby/object:Gem::Version
431
+ version: '0'
432
+ type: :development
433
+ prerelease: false
434
+ version_requirements: !ruby/object:Gem::Requirement
435
+ requirements:
436
+ - - ">="
437
+ - !ruby/object:Gem::Version
438
+ version: '0'
403
439
  description: RubyCritic is a tool that wraps around various static analysis gems to
404
440
  provide a quality report of your Ruby code.
405
441
  email:
@@ -526,7 +562,8 @@ files:
526
562
  homepage: https://github.com/whitesmith/rubycritic
527
563
  licenses:
528
564
  - MIT
529
- metadata: {}
565
+ metadata:
566
+ rubygems_mfa_required: 'true'
530
567
  post_install_message:
531
568
  rdoc_options: []
532
569
  require_paths:
@@ -542,7 +579,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
542
579
  - !ruby/object:Gem::Version
543
580
  version: '0'
544
581
  requirements: []
545
- rubygems_version: 3.1.6
582
+ rubygems_version: 3.3.7
546
583
  signing_key:
547
584
  specification_version: 4
548
585
  summary: RubyCritic is a Ruby code quality reporter