Skip to content

Commit

Permalink
Allow Rubycritic to accept config files (#286)
Browse files Browse the repository at this point in the history
* Fix include in wrong place

* Extract logic for get options from argv to a specific class

* Add parsing config file

* Fix reek and rubocop

* Remove .compact because it is not supported by previous Ruby versions

* Fix conflicts with master
  • Loading branch information
mfbmina authored and nunosilva800 committed Feb 26, 2019
1 parent 92253ec commit 987d142
Show file tree
Hide file tree
Showing 10 changed files with 259 additions and 110 deletions.
6 changes: 3 additions & 3 deletions .reek.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ detectors:
- Parser::AST::Node#module_names
- RubyCritic::Analyser::FlaySmells#run
- RubyCritic::Cli::Application#execute
- RubyCritic::Cli::Options#parse
- RubyCritic::Cli::Options::Argv#parse
- RubyCritic::CommandFactory#self.command_class
- RubyCritic::Configuration#set
- RubyCritic::Generator::Html::CodeFile#render
Expand All @@ -114,7 +114,7 @@ detectors:
exclude:
- Parser::AST::Node#recursive_children
- RubyCritic::Analyser::FlaySmells#run
- RubyCritic::Cli::Options#parse
- RubyCritic::Cli::Options::Argv#parse
- RubyCritic::Generator::HtmlReport#create_directories_and_files
- RubyCritic::AnalysedModulesCollection#initialize
UtilityFunction:
Expand All @@ -125,6 +125,7 @@ detectors:
- RubyCritic::Analyser::FlogSmells#type
- RubyCritic::Analyser::ReekSmells#smell_locations
- RubyCritic::Cli::Application#print
- RubyCritic::Cli::Options::File#value_for
- RubyCritic::AnalysedModulesCollection#limited_cost_for
- RubyCritic::Generator::Html::SmellsIndex#analysed_module_names
- RubyCritic::Generator::HtmlReport#copy_assets_to_report_directory
Expand All @@ -142,7 +143,6 @@ detectors:
- RubyCritic::Command::Compare#threshold_values_set?
TooManyInstanceVariables:
exclude:
- RubyCritic::Cli::Options
- RubyCritic::Generator::Html::CodeFile
- RubyCritic::Generator::Html::Overview
- RubyCritic::Generator::Html::SmellsIndex
Expand Down
8 changes: 7 additions & 1 deletion .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Offense count: 1
Metrics/AbcSize:
Exclude:
- 'lib/rubycritic/cli/options.rb'
- 'lib/rubycritic/cli/options/argv.rb'
- 'lib/rubycritic/configuration.rb'

# Offense count: 1
Metrics/LineLength:
Exclude:
- 'lib/rubycritic/cli/options/argv.rb'

# Offense count: 2
# Configuration parameters: CountComments.
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,25 @@ $ rubycritic --help
| `--suppress-ratings` | Suppress letter ratings |
| `--no-browser` | Do not open html report with browser |

You also can use a config file. Just create a `.rubycritic.yml` on your project root path.

Here are one example:
```
mode_ci:
enabled: true # default is false
branch: 'production' # default is master
branch: 'production' # default is master
path: '/tmp/mycustompath' # Set path where report will be saved (tmp/rubycritic by default)
threshhold_score: 10 # default is 0
deduplicate_symlinks: true # default is false
suppress_ratings: true # default is false
no_browser: true # default is false
format: console # Available values are: html, json, console, lint. Default value is html.
minimum_score: 95 # default is 0
paths: # Files to analyse.
- 'app/controllers/'
- 'app/models/'
```

### Analyzer Configuration

Expand Down
5 changes: 3 additions & 2 deletions lib/rubycritic/cli/application.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require 'rubycritic'
require 'rubycritic/browser'
require 'rubycritic/cli/options'
require 'rubycritic/command_factory'

Expand All @@ -15,9 +16,9 @@ def initialize(argv)
end

def execute
parsed_options = @options.parse
parsed_options = @options.parse.to_h

reporter = RubyCritic::CommandFactory.create(parsed_options.to_h).execute
reporter = RubyCritic::CommandFactory.create(parsed_options).execute
print(reporter.status_message)
reporter.status
rescue OptionParser::InvalidOption => error
Expand Down
108 changes: 9 additions & 99 deletions lib/rubycritic/cli/options.rb
Original file line number Diff line number Diff line change
@@ -1,117 +1,27 @@
# frozen_string_literal: true

require 'optparse'
require 'rubycritic/browser'
require 'rubycritic/cli/options/argv'
require 'rubycritic/cli/options/file'

module RubyCritic
module Cli
class Options
attr_reader :argv_options, :file_options

def initialize(argv)
@argv = argv
self.parser = OptionParser.new
@argv_options = Argv.new(argv)
@file_options = File.new
end

# rubocop:disable Metrics/MethodLength
def parse
parser.new do |opts|
opts.banner = 'Usage: rubycritic [options] [paths]'

opts.on('-p', '--path [PATH]', 'Set path where report will be saved (tmp/rubycritic by default)') do |path|
@root = path
end

opts.on('-b', '--branch BRANCH', 'Set branch to compare') do |branch|
self.base_branch = String(branch)
set_current_branch
self.mode = :compare_branches
end

opts.on('-t', '--maximum-decrease [MAX_DECREASE]',
'Set a threshold for score difference between two branches (works only with -b)') do |threshold_score|
self.threshold_score = Integer(threshold_score)
end

formats = []
self.formats = formats
opts.on(
'-f', '--format [FORMAT]',
%i[html json console lint],
'Report smells in the given format:',
' html (default; will open in a browser)',
' json',
' console',
' lint'
) do |format|
formats << format
end

opts.on('-s', '--minimum-score [MIN_SCORE]', 'Set a minimum score') do |min_score|
self.minimum_score = Float(min_score)
end

opts.on('-m', '--mode-ci [BASE_BRANCH]',
'Use CI mode (faster, analyses diffs w.r.t base_branch (default: master))') do |branch|
self.base_branch = branch || 'master'
set_current_branch
self.mode = :ci
end

opts.on('--deduplicate-symlinks', 'De-duplicate symlinks based on their final target') do
self.deduplicate_symlinks = true
end
argv_options.parse
file_options.parse

opts.on('--suppress-ratings', 'Suppress letter ratings') do
self.suppress_ratings = true
end

opts.on('--no-browser', 'Do not open html report with browser') do
self.no_browser = true
end

opts.on_tail('-v', '--version', "Show gem's version") do
self.mode = :version
end

opts.on_tail('-h', '--help', 'Show this message') do
self.mode = :help
end
end.parse!(@argv)
self
end

def to_h
{
mode: mode,
root: root,
formats: formats,
deduplicate_symlinks: deduplicate_symlinks,
paths: paths,
suppress_ratings: suppress_ratings,
help_text: parser.help,
minimum_score: minimum_score || 0,
no_browser: no_browser,
base_branch: base_branch,
feature_branch: feature_branch,
threshold_score: threshold_score || 0
}
end
# rubocop:enable Metrics/MethodLength

private

attr_accessor :mode, :root, :formats, :deduplicate_symlinks,
:suppress_ratings, :minimum_score, :no_browser,
:parser, :base_branch, :feature_branch, :threshold_score
def paths
if @argv.empty?
['.']
else
@argv
end
end

def set_current_branch
self.feature_branch = SourceControlSystem::Git.current_branch
file_options.to_h.merge(argv_options.to_h)
end
end
end
Expand Down
113 changes: 113 additions & 0 deletions lib/rubycritic/cli/options/argv.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# frozen_string_literal: true

require 'optparse'

module RubyCritic
module Cli
class Options
class Argv
def initialize(argv)
@argv = argv
self.parser = OptionParser.new
end

# rubocop:disable Metrics/MethodLength
def parse
parser.new do |opts|
opts.banner = 'Usage: rubycritic [options] [paths]'

opts.on('-p', '--path [PATH]', 'Set path where report will be saved (tmp/rubycritic by default)') do |path|
@root = path
end

opts.on('-b', '--branch BRANCH', 'Set branch to compare') do |branch|
self.base_branch = String(branch)
set_current_branch
self.mode = :compare_branches
end

opts.on('-t', '--maximum-decrease [MAX_DECREASE]', 'Set a threshold for score difference between two branches (works only with -b)') do |threshold_score|
self.threshold_score = Integer(threshold_score)
end

formats = []
self.formats = formats
opts.on(
'-f', '--format [FORMAT]',
%i[html json console lint],
'Report smells in the given format:',
' html (default; will open in a browser)',
' json',
' console',
' lint'
) do |format|
formats << format
end

opts.on('-s', '--minimum-score [MIN_SCORE]', 'Set a minimum score') do |min_score|
self.minimum_score = Float(min_score)
end

opts.on('-m', '--mode-ci [BASE_BRANCH]',
'Use CI mode (faster, analyses diffs w.r.t base_branch (default: master))') do |branch|
self.base_branch = branch || 'master'
set_current_branch
self.mode = :ci
end

opts.on('--deduplicate-symlinks', 'De-duplicate symlinks based on their final target') do
self.deduplicate_symlinks = true
end

opts.on('--suppress-ratings', 'Suppress letter ratings') do
self.suppress_ratings = true
end

opts.on('--no-browser', 'Do not open html report with browser') do
self.no_browser = true
end

opts.on_tail('-v', '--version', "Show gem's version") do
self.mode = :version
end

opts.on_tail('-h', '--help', 'Show this message') do
self.mode = :help
end
end.parse!(@argv)
end

def to_h
{
mode: mode,
root: root,
formats: formats,
deduplicate_symlinks: deduplicate_symlinks,
paths: paths,
suppress_ratings: suppress_ratings,
help_text: parser.help,
minimum_score: minimum_score,
no_browser: no_browser,
base_branch: base_branch,
feature_branch: feature_branch,
threshold_score: threshold_score
}
end
# rubocop:enable Metrics/MethodLength

private

attr_accessor :mode, :root, :formats, :deduplicate_symlinks,
:suppress_ratings, :minimum_score, :no_browser,
:parser, :base_branch, :feature_branch, :threshold_score
def paths
@argv unless @argv.empty?
end

def set_current_branch
self.feature_branch = SourceControlSystem::Git.current_branch
end
end
end
end
end
Loading

0 comments on commit 987d142

Please sign in to comment.