rubocop_plus 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,91 @@
1
+ # Temporarily disable. This cop has many false positives.
2
+ Style/AccessModifierDeclarations:
3
+ Enabled: false
4
+
5
+ # In ruby, you can define modules and classes like this:
6
+ #
7
+ # = Nested = = Compact =
8
+ # class Foo or class Foo::Bar
9
+ # class Bar end
10
+ # end
11
+ # end
12
+ #
13
+ # Style/ClassAndModuleChildren instructs rubocop to prefer 'nested' or 'compact'. The default is 'nested', but Rails typically uses
14
+ # 'compact'. Both are valid and useful strategies and there's no reason to strictly enforce one over the other.
15
+ # See https://github.com/roberts1000/rubocop_plus/issues/24
16
+ Style/ClassAndModuleChildren:
17
+ Enabled: false
18
+
19
+ # Style/EmptyMethod checks the formatting of empty methods. There are two formatting options:
20
+ #
21
+ # = expanded = vs = compact =
22
+ # def foo def foo; end
23
+ # end
24
+ #
25
+ # rubocop uses the `compact` style by default. rubocop_plus prefers the `expanded` style since it used by Rails and appears to be
26
+ # more common.
27
+ Style/EmptyMethod:
28
+ EnforcedStyle: expanded
29
+
30
+ # Frozen strings are a new feature (as of Ruby 2.3) and may become the default in a future version of Ruby. Disable this cop
31
+ # until more is known.
32
+ Style/FrozenStringLiteralComment:
33
+ Enabled: false
34
+
35
+ # Style/HashSyntax checks how hash are created. There are many ways to create a hash and they all have valid use cases. This cop has
36
+ # been disabled since it's hard to use a consistent strategy.
37
+ Style/HashSyntax:
38
+ Enabled: false
39
+
40
+ # Style/MixinUsage checks that "include" statements do not appear in the global namespace. Some 3rd party files violate this so
41
+ # we'll ignore them.
42
+ Style/MixinUsage:
43
+ Exclude:
44
+ - bin/update
45
+ - bin/setup
46
+ - spec/dummy/bin/update
47
+ - spec/dummy/bin/setup
48
+
49
+ # Style/PreferredHashMethods checks if hash methods like 'has_key?' or 'has_value?' are called, then recommends they be switched
50
+ # to 'key?' and 'value?'. rubocop_plus perfers the use of predicates on method names since they make the code questions more
51
+ # precise. Also, the Naming/PredicateName cop has been disabled in this file and that cop checks for a similar
52
+ # pattern on custom methods. For consistency, the more verbose form (like 'has_key?') is preferred when working with Hashes.
53
+ Style/PreferredHashMethods:
54
+ EnforcedStyle: verbose
55
+
56
+ # Style/StringLiterals enforces the use of single quotes around string literals. The major argument for using single quotes is
57
+ # they should be faster than double quotes (which need to be parsed for possible uses of interpolation). Also, they help reveal
58
+ # intention by alerting developers that there is no interpolation in the string. However, there is no performance difference
59
+ # between using single and double quoted strings (https://www.viget.com/articles/just-use-double-quoted-ruby-strings) and
60
+ # we consider any semantic advantages to be not worth the effort. We have disabled this cop and advocate that developers
61
+ # "try" to be consistent within an individual file.
62
+ Style/StringLiterals:
63
+ Enabled: false
64
+
65
+ # Style/SingleLineBlockParams requires parameters to have standard names in blocks. rubocop considers the following to be bad:
66
+ #
67
+ # [1, 2, 3].inject(0) { |sum, a| sum + a }
68
+ #
69
+ # Instead, this is preferred
70
+ #
71
+ # [1, 2, 3].inject(0) { |acc, elem| acc + elem }
72
+ #
73
+ # "acc" means "acc"umulator and "e" means "elem"ent. Forcing everyone to use the same variable names does standardizes things,
74
+ # but it can decrease readability. Unique variable names which impart meaning are better.
75
+ Style/SingleLineBlockParams:
76
+ Enabled: false
77
+
78
+ # Style/StderrPuts suggests using `warn` over `$stderr.puts`. Some 3rd party files violate this so we'll ignore them.
79
+ Style/StderrPuts:
80
+ Exclude:
81
+ - bin/yarn
82
+ - spec/dummy/bin/yarn
83
+
84
+ # Style/SymbolArray checks if %i or %I are used to create symbol arrays. rubocop recommends
85
+ #
86
+ # = Good = = Bad =
87
+ # %i[foo bar] [:foo, :bar]
88
+ #
89
+ # The direct symbol form is easier to read and follows Rails.
90
+ Style/SymbolArray:
91
+ Enabled: false
@@ -0,0 +1,22 @@
1
+ require:
2
+ - rubocop-performance
3
+ - rubocop-rails
4
+ - rubocop-rspec
5
+
6
+ AllCops:
7
+ Exclude: # skip all of the following....
8
+ - db/schema.rb # An auto-generated file
9
+ - spec/dummy/db/schema.rb # An auto-generated file
10
+ - lib/tasks/cucumber.rake # A 3rd-party auto-generated file
11
+ - vendor/**/* # Contains 3rd party libs; no need to check code that originated outside the project
12
+ - node_modules/**/* # Yarn 3rd party dependencies; no need to check code that originated outside the project
13
+ - client/**/* # It's mostly JavaScript, but it may contain 3rd party that was written outside of the project
14
+
15
+ inherit_from:
16
+ - group/layout.yml
17
+ - group/lint.yml
18
+ - group/metrics.yml
19
+ - group/naming.yml
20
+ - group/rails.yml
21
+ - group/rspec.yml
22
+ - group/style.yml
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This script runs rubocop with some default output specifications. Output is written to a 'rubocop/' folder into the root
4
+ # of an application. This script can be invoked by running the following commands in the root of a ruby gem, rails engine
5
+ # or rails application:
6
+ #
7
+ # EXECUTION
8
+ #
9
+ # rubo # Run rubocop with the defaults.
10
+ # rubo -h # View the help file to see more options.
11
+ #
12
+ # EXIT STATUS
13
+ #
14
+ # See the bottom of the file for exit status codes and their meaning.
15
+
16
+ lib = File.expand_path('../lib', __dir__)
17
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
18
+
19
+ require "cri"
20
+ require 'commands/rubo'
21
+ require "commands/rubo/utils/cri_platform_monkey_patch"
22
+
23
+ # rubocop:disable Metrics/BlockLength
24
+ command = Cri::Command.define do
25
+ # name 'rubo'
26
+ usage 'rubo [options]'
27
+ # aliases :ds, :stuff
28
+ # summary 'foo'
29
+ description 'rubo is an executable installed by the rubocop_plus gem. It invokes rubocop with a custom set of ' \
30
+ "rules. The following status codes are returned:\n\n" \
31
+ "STATUS CODES\n\n" \
32
+ "0 - rubocop ran and results were written to the 'rubocop' folder........\n" \
33
+ "1 - the project root does not contain a .rubocop.yml file...............\n" \
34
+ "2 - the .rubocop.yml file does not have the correct content.............\n" \
35
+ "3 - the 'rubocop' command cound not be found (likely due to missing gem)\n" \
36
+ "4 - the output from the 'rubo' command is missing or corrupt............\n"
37
+
38
+ flag :h, :help, 'show help for this command' do |_value, cmd|
39
+ puts cmd.help
40
+ exit 0
41
+ end
42
+
43
+ flag :i, :init, "(re)initialize your project with starting files; this will overwrite existing files" do |_value, cmd|
44
+ RubocopPlus::Commands::Rubo.new({ validate: true }, {}, cmd).initialize_project
45
+ exit 0
46
+ end
47
+
48
+ # This option is helpful when we're printing results to places that don't support the terminal colors (like the Jenkins
49
+ # console output). It also helps other tools parse the results of a successful run since the output doesn't contain extra
50
+ # numeric characters.
51
+ flag nil, "no-color", "do not colorize the output"
52
+
53
+ # This method should return a proper exit status if there are errors determining the rubocop version.
54
+ flag nil, "rubocop-version", 'return the version of rubocop' do |_value, cmd|
55
+ rubo = RubocopPlus::Commands::Rubo.new({ validate: true }, {}, cmd)
56
+ rubo.check_if_rubocop_command_exists!
57
+ puts rubo.rubocop_version_name
58
+ exit 0
59
+ end
60
+
61
+ # This method should return a proper exit status if there are errors determining the total violations count.
62
+ flag :t, "total-violations", 'write the total violations' do |_value, cmd|
63
+ rubo = RubocopPlus::Commands::Rubo.new({ total_violations: true }, {}, cmd)
64
+ rubo.check_if_total_violations_count_still_present_and_valid!
65
+ puts rubo.total_violations_count
66
+ exit 0
67
+ end
68
+
69
+ # This method should return a proper exit status if there are validation errors.
70
+ flag nil, :validate, "make sure rubocop is runnable" do |_value, cmd|
71
+ RubocopPlus::Commands::Rubo.new({ validate: true }, {}, cmd).validate_pre_run!
72
+ puts "Everything looks great!"
73
+ exit 0
74
+ end
75
+
76
+ flag :v, :version, 'return the version of rubo' do |_value, _cmd|
77
+ require 'rubocop_plus/version'
78
+ puts RubocopPlus::VERSION
79
+ exit 0
80
+ end
81
+
82
+ run do |options, args, cmd|
83
+ RubocopPlus::Commands::Rubo.new(options, args, cmd).run
84
+ end
85
+ end
86
+ # rubocop:enable Metrics/BlockLength
87
+
88
+ begin
89
+ command.run(ARGV)
90
+ exit 0
91
+ # Raised when an application fails to include a .rubocop.yml file.
92
+ rescue RubocopPlus::Commands::MissingYml => e
93
+ warn e.message
94
+ exit 1
95
+ # Raised when a project has a .rubocop.yml file, but it doesn't contain the correct content to work with this gem.
96
+ rescue RubocopPlus::Commands::IncorrectYml => e
97
+ warn e.message
98
+ exit 2
99
+ # Raised when the needed version of the rubocop executable is not installed (like because the rubocop gem is not installed).
100
+ rescue RubocopPlus::Commands::NoRubocopCommand => e
101
+ warn e.message
102
+ exit 3
103
+ # Raised when there are issues with the output generated by rubo.
104
+ rescue RubocopPlus::Commands::BadOutput, RubocopPlus::Commands::OutputMissing => e
105
+ warn e.message
106
+ exit 4
107
+ end
@@ -0,0 +1,102 @@
1
+ require "rubocop_plus"
2
+
3
+ require_relative "rubo/utils/which"
4
+ require_relative "rubo/helpers/misc"
5
+ require_relative "rubo/helpers/output"
6
+ require_relative "rubo/helpers/validations"
7
+
8
+ require_relative "rubo/errors/missing_yml"
9
+ require_relative "rubo/errors/incorrect_yml"
10
+ require_relative "rubo/errors/no_rubocop_command"
11
+ require_relative "rubo/errors/bad_output"
12
+ require_relative "rubo/errors/output_missing"
13
+
14
+ module RubocopPlus
15
+ module Commands
16
+ # The main class for the rubo command. When rubo is invoked on the command line, this class is initiated and the 'run'
17
+ # method is called.
18
+ class Rubo < Cri::CommandRunner
19
+ def run
20
+ prepare_options
21
+ validate_pre_run!
22
+ write_starting_message
23
+ delete_rubocop_folder
24
+ invoke_rubocop
25
+ generate_total_violations_file
26
+ validate_post_run!
27
+ write_results_message
28
+ end
29
+
30
+ # Perform all of the checks to make sure rubo can actually run. This method is called by the 'run' method when
31
+ # 'rubo' is called. It's also called with 'rubo --validate' is called.
32
+ def validate_pre_run!
33
+ check_if_yml_present!
34
+ check_if_yml_has_correct_content!
35
+ check_if_rubocop_command_exists!
36
+ end
37
+
38
+ def validate_post_run!
39
+ check_if_results_exist!
40
+ end
41
+
42
+ def initialize_project
43
+ backup_rubocop_yml_if_present
44
+ template_path = File.expand_path('../templates/.rubocop.yml', __dir__)
45
+ FileUtils.cp(template_path, ".rubocop.yml")
46
+ puts ".rubocop.yml created"
47
+ end
48
+
49
+ # Execute rubocop with a tailored set of output files. Rails checks are activated in the default config/rubocop.yml file
50
+ # so we do not explicitly activate them there.
51
+ def invoke_rubocop
52
+ cmd = is_in_gemfile_dot_lock? ? "bundle exec rubocop" : "rubocop"
53
+ # Make sure we always use the specific version of rubocop. Without this line, the latest version of rubocop
54
+ # will be used if a user installs a version that is newer than what we want to use.
55
+ cmd += " _#{RubocopPlus::RUBOCOP_VERSION}_"
56
+ cmd += " --format simple --out #{style_issues_text_file_name}"
57
+ cmd += " --format html --out #{style_issues_html_file_name}"
58
+ cmd += " --format offenses --out #{style_counts_text_file_name}"
59
+ cmd += checkstyle_options
60
+ system cmd
61
+ end
62
+
63
+ # Generates the XML reports necessary to use the Checkstyle Plugin on Jenkins. It is only needed for the CI so return an
64
+ # empty string unless the --checkstyle option is present.
65
+ def checkstyle_options
66
+ return "" unless options[:checkstyle]
67
+
68
+ cmd = " --require rubocop/formatter/checkstyle_formatter"
69
+ cmd += " --format RuboCop::Formatter::CheckstyleFormatter"
70
+ cmd + " --out #{output_folder_name}/checkstyle.xml"
71
+ end
72
+
73
+ # While using SublimeText with the SFTP plugin, we noticed the SFTP plugin would not automatically download newer versions
74
+ # of the generated rubocop files at times. Rubocop should overwrite the files, but we goahead and explicity delete the
75
+ # folder in the hopes that will help resolve the file syncing issues for editors (we're not 100% sure this helps).
76
+ def delete_rubocop_folder
77
+ FileUtils.remove_dir(output_folder_name, true)
78
+ end
79
+
80
+ private
81
+
82
+ def backup_rubocop_yml_if_present
83
+ return unless File.file?(".rubocop.yml")
84
+
85
+ FileUtils.mv(".rubocop.yml", ".rubocop.yml.bak")
86
+ puts ".rubocop.yml renamed to .rubocop.yml.bak"
87
+ end
88
+
89
+ # The cri doesn't do a good job of preparing the options. Instead of having symbols like :"no-color", :no_color is better.
90
+ def prepare_options
91
+ normalize_options
92
+ String.allow_color = !options[:no_color]
93
+ end
94
+
95
+ def normalize_options
96
+ no_color = options.delete(:"no-color")
97
+ options[:no_color] = no_color.nil? ? false : no_color
98
+ options[:checkstyle] = false unless options.has_key?(:checkstyle)
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,18 @@
1
+ module RubocopPlus
2
+ module Commands
3
+ # When the rubo command runs rubocop, it tells rubocop to output to a specific set of files. If those files aren't
4
+ # created, (or don't have the expected format), rubo will raise a BadOutput error.
5
+ class BadOutput < StandardError
6
+ def initialize(msg="")
7
+ @details = msg
8
+ super
9
+ end
10
+
11
+ def message
12
+ "Error\n\n" \
13
+ " The output in the rubocop folder does not look correct. This implies rubo wasn't able to run 'rubocop'\n" \
14
+ " for some reason: #{@details}.\n\n".rubo_red
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ module RubocopPlus
2
+ module Commands
3
+ # The rubo command performs some sanity checking to make sure the current application is using a well defined
4
+ # .rubocop.yml. It problems are found, an IncorrectYml error is raised.
5
+ class IncorrectYml < StandardError
6
+ def message
7
+ "\n" \
8
+ " The .rubocop.yml file does not appear to have the correct configuration to read from the\n" \
9
+ " rubocop_plus gem. To correct the problem:\n" \
10
+ " 1. Rename your existing .rubocop.yml to .rubocop.yml.bak\n" \
11
+ " 2. Run the installer to generate a fresh .rubocop.yml\n" \
12
+ " rubo --init\n\n".rubo_red
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ module RubocopPlus
2
+ module Commands
3
+ # The rubo command performs some sanity checking to make sure the current application is using a well defined
4
+ # .rubocop.yml. If the .rubocop.yml file is missing, a MissingYml error is raised.
5
+ class MissingYml < StandardError
6
+ def message
7
+ "\n The application does not have a .rubocop.yml file. Run the installer to generate one:\n" \
8
+ " rubo --init\n\n".rubo_red
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ module RubocopPlus
2
+ module Commands
3
+ # The rubo command will check to make sure the `rubocop` command exists. When users install rubocop_plus, rubocop_plus
4
+ # will automatically install a version of rubocop. Users may delete rubocop at a later time. If rubocop isn't available
5
+ # on the system, NoRubocopCommand will be raised.
6
+ class NoRubocopCommand < StandardError
7
+ def message
8
+ "\n" \
9
+ " The 'rubocop' command is not available. Is the rubocop gem installed? Verify by executing\n" \
10
+ " 'gem list rubocop'. If rubocop is not listed, reinstall rubocop_plus.\n\n".rubo_red
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ module RubocopPlus
2
+ module Commands
3
+ # The rubo command will generate some custom output files. If those files don't get created properly, rubo will raise
4
+ # OutputMissing.
5
+ class OutputMissing < StandardError
6
+ def initialize(msg="")
7
+ @message = msg
8
+ super
9
+ end
10
+
11
+ def message
12
+ @message.rubo_red
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,68 @@
1
+ module RubocopPlus
2
+ module Commands
3
+ # Miscellaneous helpers are grouped in this file.
4
+ class Rubo < Cri::CommandRunner
5
+ def rubocop_yml_present?
6
+ File.file?(".rubocop.yml")
7
+ end
8
+
9
+ # The Gemfile.lock is auto generated when the 'bundle' command is run. It doesn't contain superfluous comments or any
10
+ # references to a gem unless the gem is being used. However, many terms like 'rails' is used in multiple gem name so
11
+ # we need to be smart about checking boundaries. Each gem line in Gemfile.lock always starts with a couple spaces,
12
+ # followed by the gem name, followed by a single space or newline chracter.
13
+ def is_in_gemfile_dot_lock?
14
+ return false unless File.exist?("Gemfile.lock")
15
+
16
+ # Match logic
17
+ # ^ - match from beginning of string
18
+ # \s* - match 0-N white space characters
19
+ # rubocop_plus - match the gem_name exactly once
20
+ # \s - match one white space character (it will always be a space or a \n)
21
+ File.foreach("Gemfile.lock") { |line| return true if line =~ /^\s*rubocop_plus\s/ }
22
+ false
23
+ end
24
+
25
+ def installed_version_of_gem
26
+ Gem::Version.new(RubocopPlus::VERSION)
27
+ end
28
+
29
+ def rubocop_version_name
30
+ Gem::Version.new(RubocopPlus::RUBOCOP_VERSION)
31
+ end
32
+
33
+ def output_folder_name
34
+ "rubocop"
35
+ end
36
+
37
+ def style_issues_text_file_name
38
+ "#{output_folder_name}/style-issues.txt"
39
+ end
40
+
41
+ def style_issues_html_file_name
42
+ "#{output_folder_name}/style-issues.html"
43
+ end
44
+
45
+ def style_counts_text_file_name
46
+ "#{output_folder_name}/style-counts.txt"
47
+ end
48
+
49
+ def total_violations_count_text_file_name
50
+ "#{output_folder_name}/total-violations-count.txt"
51
+ end
52
+
53
+ # Perform some sanity checks to make sure .rubocop.yml has expected content.
54
+ def rubocop_yml_has_correct_content?
55
+ # If we're running from inside the rubocop_plus folder, ignore this check.
56
+ return true if Dir.pwd.include?("rubocop_plus")
57
+
58
+ text = File.read(".rubocop.yml")
59
+ text.include?("inherit_gem:") && text.include?("rubocop_plus:")
60
+ end
61
+
62
+ def rubocop_command_exists?
63
+ path = Which('rubocop')
64
+ !(path.nil? || path.empty?)
65
+ end
66
+ end
67
+ end
68
+ end