diff --git a/Gemfile b/Gemfile index 6ca59850..bb1502cb 100644 --- a/Gemfile +++ b/Gemfile @@ -4,9 +4,9 @@ source 'https://rubygems.org' gem "activesupport", require: false gem "mry", "~> 0.52.0", require: false -gem "parser", "~> 2.4.0" +gem "parser" gem "pry", require: false -gem "rubocop", "~> 0.52.1", require: false +gem "rubocop", "~> 0.68.1", require: false gem "rubocop-migrations", require: false gem "rubocop-rspec", require: false gem "safe_yaml" diff --git a/Gemfile.lock b/Gemfile.lock index 6231ee3c..1b3e5a73 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,20 +6,20 @@ GEM i18n (~> 0.7) minitest (~> 5.1) tzinfo (~> 1.1) - ast (2.3.0) + ast (2.4.0) coderay (1.1.2) concurrent-ruby (1.0.5) diff-lcs (1.3) i18n (0.9.1) concurrent-ruby (~> 1.0) + jaro_winkler (1.5.2) method_source (0.9.0) minitest (5.10.3) mry (0.52.0.0) rubocop (>= 0.41.0) - parallel (1.12.1) - parser (2.4.0.2) - ast (~> 2.3) - powerpack (0.1.1) + parallel (1.17.0) + parser (2.6.3.0) + ast (~> 2.4.0) pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) @@ -38,23 +38,23 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.7.0) rspec-support (3.7.0) - rubocop (0.52.1) + rubocop (0.68.1) + jaro_winkler (~> 1.5.1) parallel (~> 1.10) - parser (>= 2.4.0.2, < 3.0) - powerpack (~> 0.1) + parser (>= 2.5, != 2.5.1.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) - unicode-display_width (~> 1.0, >= 1.0.1) + unicode-display_width (>= 1.4.0, < 1.6) rubocop-migrations (0.1.2) rubocop (~> 0.41) rubocop-rspec (1.21.0) rubocop (>= 0.52.0) - ruby-progressbar (1.9.0) + ruby-progressbar (1.10.0) safe_yaml (1.0.4) thread_safe (0.3.6) tzinfo (1.2.4) thread_safe (~> 0.1) - unicode-display_width (1.3.0) + unicode-display_width (1.5.0) PLATFORMS ruby @@ -62,14 +62,14 @@ PLATFORMS DEPENDENCIES activesupport mry (~> 0.52.0) - parser (~> 2.4.0) + parser pry rake rspec - rubocop (~> 0.52.1) + rubocop (~> 0.68.1) rubocop-migrations rubocop-rspec safe_yaml BUNDLED WITH - 1.16.1 + 1.16.6 diff --git a/config/contents/bundler/gem_comment.md b/config/contents/bundler/gem_comment.md new file mode 100644 index 00000000..ac48aa5e --- /dev/null +++ b/config/contents/bundler/gem_comment.md @@ -0,0 +1,11 @@ +Add a comment describing each gem in your Gemfile. + +### Example: + # bad + + gem 'foo' + + # good + + # Helpers for the foo things. + gem 'foo' diff --git a/config/contents/bundler/insecure_protocol_source.md b/config/contents/bundler/insecure_protocol_source.md index b405c76f..e5a43280 100644 --- a/config/contents/bundler/insecure_protocol_source.md +++ b/config/contents/bundler/insecure_protocol_source.md @@ -1,4 +1,4 @@ -The symbol argument `:gemcutter`, `:rubygems` and `:rubyforge` +The symbol argument `:gemcutter`, `:rubygems`, and `:rubyforge` are deprecated. So please change your source to URL string that 'https://rubygems.org' if possible, or 'http://rubygems.org' if not. diff --git a/config/contents/gemspec/duplicated_assignment.md b/config/contents/gemspec/duplicated_assignment.md index cfcb10ab..6afaac86 100644 --- a/config/contents/gemspec/duplicated_assignment.md +++ b/config/contents/gemspec/duplicated_assignment.md @@ -3,7 +3,7 @@ in a gemspec. Assigning to an attribute with the same name using `spec.foo =` will be an unintended usage. On the other hand, duplication of methods such -as `spec.requirements`, `spec.add_runtime_dependency` and others are +as `spec.requirements`, `spec.add_runtime_dependency`, and others are permitted because it is the intended use of appending values. ### Example: diff --git a/config/contents/layout/access_modifier_indentation.md b/config/contents/layout/access_modifier_indentation.md index a91ed86b..096ab569 100644 --- a/config/contents/layout/access_modifier_indentation.md +++ b/config/contents/layout/access_modifier_indentation.md @@ -1,5 +1,6 @@ -Modifiers should be indented as deep as method definitions, or as deep -as the class/module keyword, depending on configuration. +Bare access modifiers (those not applying to specific methods) should be +indented as deep as method definitions, or as deep as the class/module +keyword, depending on configuration. ### Example: EnforcedStyle: indent (default) # bad diff --git a/config/contents/layout/align_arguments.md b/config/contents/layout/align_arguments.md new file mode 100644 index 00000000..d90af9ec --- /dev/null +++ b/config/contents/layout/align_arguments.md @@ -0,0 +1,34 @@ +Here we check if the arguments on a multi-line method +definition are aligned. + +### Example: EnforcedStyle: with_first_argument (default) + # good + + foo :bar, + :baz + + foo( + :bar, + :baz + ) + + # bad + + foo :bar, + :baz + + foo( + :bar, + :baz + ) + +### Example: EnforcedStyle: with_fixed_indentation + # good + + foo :bar, + :baz + + # bad + + foo :bar, + :baz \ No newline at end of file diff --git a/config/contents/layout/align_hash.md b/config/contents/layout/align_hash.md index 1842159b..57cf9ab9 100644 --- a/config/contents/layout/align_hash.md +++ b/config/contents/layout/align_hash.md @@ -2,7 +2,7 @@ Check that the keys, separators, and values of a multi-line hash literal are aligned according to configuration. The configuration options are: - - key (left align keys) + - key (left align keys, one space before hash rockets and values) - separator (align hash rockets and colons, right align keys) - table (left align keys, hash rockets, and values) @@ -14,81 +14,156 @@ can also be configured. The options are: - ignore_implicit (without curly braces) - ignore_explicit (with curly braces) -### Example: - - # EnforcedHashRocketStyle: key (default) - # EnforcedColonStyle: key (default) - - # good +### Example: EnforcedHashRocketStyle: key (default) + # bad { - foo: bar, - ba: baz + :foo => bar, + :ba => baz + } + { + :foo => bar, + :ba => baz } + + # good { :foo => bar, :ba => baz } +### Example: EnforcedHashRocketStyle: separator # bad { - foo: bar, - ba: baz + :foo => bar, + :ba => baz } { :foo => bar, - :ba => baz + :ba => baz } -### Example: - - # EnforcedHashRocketStyle: separator - # EnforcedColonStyle: separator - - #good - { - foo: bar, - ba: baz - } + # good { :foo => bar, :ba => baz } - #bad - { - foo: bar, - ba: baz - } +### Example: EnforcedHashRocketStyle: table + # bad { :foo => bar, - :ba => baz + :ba => baz } + + # good { :foo => bar, :ba => baz } -### Example: +### Example: EnforcedColonStyle: key (default) + # bad + { + foo: bar, + ba: baz + } + { + foo: bar, + ba: baz + } - # EnforcedHashRocketStyle: table - # EnforcedColonStyle: table + # good + { + foo: bar, + ba: baz + } - #good +### Example: EnforcedColonStyle: separator + # bad { foo: bar, - ba: baz + ba: baz } + + # good { - :foo => bar, - :ba => baz + foo: bar, + ba: baz } - #bad +### Example: EnforcedColonStyle: table + # bad { foo: bar, ba: baz } + + # good { - :foo => bar, - :ba => baz - } \ No newline at end of file + foo: bar, + ba: baz + } + +### Example: EnforcedLastArgumentHashStyle: always_inspect (default) + # Inspect both implicit and explicit hashes. + + # bad + do_something(foo: 1, + bar: 2) + + # bad + do_something({foo: 1, + bar: 2}) + + # good + do_something(foo: 1, + bar: 2) + + # good + do_something( + foo: 1, + bar: 2 + ) + + # good + do_something({foo: 1, + bar: 2}) + + # good + do_something({ + foo: 1, + bar: 2 + }) + +### Example: EnforcedLastArgumentHashStyle: always_ignore + # Ignore both implicit and explicit hashes. + + # good + do_something(foo: 1, + bar: 2) + + # good + do_something({foo: 1, + bar: 2}) + +### Example: EnforcedLastArgumentHashStyle: ignore_implicit + # Ignore only implicit hashes. + + # bad + do_something({foo: 1, + bar: 2}) + + # good + do_something(foo: 1, + bar: 2) + +### Example: EnforcedLastArgumentHashStyle: ignore_explicit + # Ignore only explicit hashes. + + # bad + do_something(foo: 1, + bar: 2) + + # good + do_something({foo: 1, + bar: 2}) diff --git a/config/contents/layout/align_parameters.md b/config/contents/layout/align_parameters.md index c6848abc..ec3d2d29 100644 --- a/config/contents/layout/align_parameters.md +++ b/config/contents/layout/align_parameters.md @@ -1,24 +1,65 @@ Here we check if the parameters on a multi-line method call or definition are aligned. +To set the alignment of the first argument, use the cop +FirstParameterIndentation. + ### Example: EnforcedStyle: with_first_parameter (default) # good - foo :bar, - :baz + def foo(bar, + baz) + 123 + end + + def foo( + bar, + baz + ) + 123 + end + + # bad + + def foo(bar, + baz) + 123 + end # bad - foo :bar, - :baz + def foo( + bar, + baz) + 123 + end ### Example: EnforcedStyle: with_fixed_indentation # good - foo :bar, - :baz + def foo(bar, + baz) + 123 + end + + def foo( + bar, + baz + ) + 123 + end + + # bad + + def foo(bar, + baz) + 123 + end # bad - foo :bar, - :baz \ No newline at end of file + def foo( + bar, + baz) + 123 + end \ No newline at end of file diff --git a/config/contents/layout/block_alignment.md b/config/contents/layout/block_alignment.md new file mode 100644 index 00000000..dfd9d13c --- /dev/null +++ b/config/contents/layout/block_alignment.md @@ -0,0 +1,58 @@ +This cop checks whether the end keywords are aligned properly for do +end blocks. + +Three modes are supported through the `EnforcedStyleAlignWith` +configuration parameter: + +`start_of_block` : the `end` shall be aligned with the +start of the line where the `do` appeared. + +`start_of_line` : the `end` shall be aligned with the +start of the line where the expression started. + +`either` (which is the default) : the `end` is allowed to be in either +location. The autofixer will default to `start_of_line`. + +### Example: EnforcedStyleAlignWith: either (default) + # bad + + foo.bar + .each do + baz + end + + # good + + variable = lambda do |i| + i + end + +### Example: EnforcedStyleAlignWith: start_of_block + # bad + + foo.bar + .each do + baz + end + + # good + + foo.bar + .each do + baz + end + +### Example: EnforcedStyleAlignWith: start_of_line + # bad + + foo.bar + .each do + baz + end + + # good + + foo.bar + .each do + baz + end \ No newline at end of file diff --git a/config/contents/layout/class_structure.md b/config/contents/layout/class_structure.md index b4691836..849e6e74 100644 --- a/config/contents/layout/class_structure.md +++ b/config/contents/layout/class_structure.md @@ -3,35 +3,43 @@ Checks if the code style follows the ExpectedOrder configuration: `Categories` allows us to map macro names into a category. Consider an example of code style that covers the following order: +- Module inclusion (include, prepend, extend) - Constants - Associations (has_one, has_many) -- Attributes (attr_accessor, attr_writer, attr_reader) +- Public attribute macros (attr_accessor, attr_writer, attr_reader) +- Other macros (validates, validate) +- Public class methods - Initializer -- Instance methods -- Protected methods -- Private methods +- Public instance methods +- Protected attribute macros (attr_accessor, attr_writer, attr_reader) +- Protected instance methods +- Private attribute macros (attr_accessor, attr_writer, attr_reader) +- Private instance methods You can configure the following order: ```yaml Layout/ClassStructure: - Categories: - module_inclusion: - - include - - prepend - - extend ExpectedOrder: - - module_inclusion - - constants - - public_class_methods - - initializer - - public_methods - - protected_methods - - private_methods - + - module_inclusion + - constants + - association + - public_attribute_macros + - public_delegate + - macros + - public_class_methods + - initializer + - public_methods + - protected_attribute_macros + - protected_methods + - private_attribute_macros + - private_delegate + - private_methods ``` + Instead of putting all literals in the expected order, is also -possible to group categories of macros. +possible to group categories of macros. Visibility levels are handled +automatically. ```yaml Layout/ClassStructure: @@ -39,10 +47,17 @@ possible to group categories of macros. association: - has_many - has_one - attribute: + attribute_macros: - attr_accessor - attr_reader - attr_writer + macros: + - validates + - validate + module_inclusion: + - include + - prepend + - extend ``` ### Example: @@ -68,12 +83,15 @@ possible to group categories of macros. # constants are next SOME_CONSTANT = 20 - # afterwards we have attribute macros + # afterwards we have public attribute macros attr_reader :name # followed by other macros (if any) validates :name + # then we have public delegate macros + delegate :to_s, to: :name + # public class methods are next in line def self.some_method end @@ -86,16 +104,24 @@ possible to group categories of macros. def some_method end - # protected and private methods are grouped near the end + # protected attribute macros and methods go next protected + attr_reader :protected_name + def some_protected_method end + # private attribute macros, delegate macros and methods + # are grouped near the end private + attr_reader :private_name + + delegate :some_private_delegate, to: :name + def some_private_method end end -@see https://github.com/bbatsov/ruby-style-guide#consistent-classes \ No newline at end of file +@see https://github.com/rubocop-hq/ruby-style-guide#consistent-classes \ No newline at end of file diff --git a/config/contents/layout/closing_heredoc_indentation.md b/config/contents/layout/closing_heredoc_indentation.md new file mode 100644 index 00000000..6a78ff4d --- /dev/null +++ b/config/contents/layout/closing_heredoc_indentation.md @@ -0,0 +1,42 @@ + +Checks the indentation of here document closings. + +### Example: + + # bad + class Foo + def bar + <<~SQL + 'Hi' + SQL + end + end + + # good + class Foo + def bar + <<~SQL + 'Hi' + SQL + end + end + + # bad + + # heredoc contents is before closing heredoc. + foo arg, + <<~EOS + Hi + EOS + + # good + foo arg, + <<~EOS + Hi + EOS + + # good + foo arg, + <<~EOS + Hi + EOS diff --git a/config/contents/layout/closing_parenthesis_indentation.md b/config/contents/layout/closing_parenthesis_indentation.md index f7092715..ac4fbef4 100644 --- a/config/contents/layout/closing_parenthesis_indentation.md +++ b/config/contents/layout/closing_parenthesis_indentation.md @@ -1,23 +1,64 @@ -This cops checks the indentation of hanging closing parentheses in +This cop checks the indentation of hanging closing parentheses in method calls, method definitions, and grouped expressions. A hanging closing parenthesis means `)` preceded by a line break. ### Example: - # good: when x is on its own line, indent this way - func( - x, - y - ) + # bad + some_method( + a, + b + ) - # good: when x follows opening parenthesis, align parentheses - a = b * (x + - y - ) + some_method( + a, b + ) - # bad - def func( - x, - y + some_method(a, b, c ) - end \ No newline at end of file + + some_method(a, + b, + c + ) + + some_method(a, + x: 1, + y: 2 + ) + + # Scenario 1: When First Parameter Is On Its Own Line + + # good: when first param is on a new line, right paren is *always* + # outdented by IndentationWidth + some_method( + a, + b + ) + + # good + some_method( + a, b + ) + + # Scenario 2: When First Parameter Is On The Same Line + + # good: when all other params are also on the same line, outdent + # right paren by IndentationWidth + some_method(a, b, c + ) + + # good: when all other params are on multiple lines, but are lined + # up, align right paren with left paren + some_method(a, + b, + c + ) + + # good: when other params are not lined up on multiple lines, outdent + # right paren by IndentationWidth + some_method(a, + x: 1, + y: 2 + ) + diff --git a/config/contents/layout/comment_indentation.md b/config/contents/layout/comment_indentation.md index 34dd43a9..3d2c7c1c 100644 --- a/config/contents/layout/comment_indentation.md +++ b/config/contents/layout/comment_indentation.md @@ -1,4 +1,4 @@ -This cops checks the indentation of comments. +This cop checks the indentation of comments. ### Example: # bad diff --git a/config/contents/layout/condition_position.md b/config/contents/layout/condition_position.md new file mode 100644 index 00000000..5f4557fd --- /dev/null +++ b/config/contents/layout/condition_position.md @@ -0,0 +1,19 @@ +This cop checks for conditions that are not on the same line as +if/while/until. + +### Example: + + # bad + + if + some_condition + do_something + end + +### Example: + + # good + + if some_condition + do_something + end \ No newline at end of file diff --git a/config/contents/layout/def_end_alignment.md b/config/contents/layout/def_end_alignment.md new file mode 100644 index 00000000..05d6a6bc --- /dev/null +++ b/config/contents/layout/def_end_alignment.md @@ -0,0 +1,30 @@ +This cop checks whether the end keywords of method definitions are +aligned properly. + +Two modes are supported through the EnforcedStyleAlignWith configuration +parameter. If it's set to `start_of_line` (which is the default), the +`end` shall be aligned with the start of the line where the `def` +keyword is. If it's set to `def`, the `end` shall be aligned with the +`def` keyword. + +### Example: EnforcedStyleAlignWith: start_of_line (default) + # bad + + private def foo + end + + # good + + private def foo + end + +### Example: EnforcedStyleAlignWith: def + # bad + + private def foo + end + + # good + + private def foo + end \ No newline at end of file diff --git a/config/contents/layout/dot_position.md b/config/contents/layout/dot_position.md index ffabb960..4f25b42f 100644 --- a/config/contents/layout/dot_position.md +++ b/config/contents/layout/dot_position.md @@ -3,7 +3,7 @@ This cop checks the . position in multi-line method calls. ### Example: EnforcedStyle: leading (default) # bad something. - mehod + method # good something @@ -16,4 +16,4 @@ This cop checks the . position in multi-line method calls. # good something. - mehod \ No newline at end of file + method \ No newline at end of file diff --git a/config/contents/layout/else_alignment.md b/config/contents/layout/else_alignment.md index decaeb7d..6c577dd9 100644 --- a/config/contents/layout/else_alignment.md +++ b/config/contents/layout/else_alignment.md @@ -1,4 +1,4 @@ -This cops checks the alignment of else keywords. Normally they should +This cop checks the alignment of else keywords. Normally they should be aligned with an if/unless/while/until/begin/def keyword, but there are special cases when they should follow the same rules as the alignment of end. diff --git a/config/contents/layout/empty_comment.md b/config/contents/layout/empty_comment.md new file mode 100644 index 00000000..5c89b7b3 --- /dev/null +++ b/config/contents/layout/empty_comment.md @@ -0,0 +1,56 @@ +This cop checks empty comment. + +### Example: + # bad + + # + class Foo + end + + # good + + # + # Description of `Foo` class. + # + class Foo + end + +### Example: AllowBorderComment: true (default) + # good + + def foo + end + + ################# + + def bar + end + +### Example: AllowBorderComment: false + # bad + + def foo + end + + ################# + + def bar + end + +### Example: AllowMarginComment: true (default) + # good + + # + # Description of `Foo` class. + # + class Foo + end + +### Example: AllowMarginComment: false + # bad + + # + # Description of `Foo` class. + # + class Foo + end diff --git a/config/contents/layout/empty_line_after_guard_clause.md b/config/contents/layout/empty_line_after_guard_clause.md new file mode 100644 index 00000000..cb271393 --- /dev/null +++ b/config/contents/layout/empty_line_after_guard_clause.md @@ -0,0 +1,32 @@ +This cop enforces empty line after guard clause + +### Example: + + # bad + def foo + return if need_return? + bar + end + + # good + def foo + return if need_return? + + bar + end + + # good + def foo + return if something? + return if something_different? + + bar + end + + # also good + def foo + if something? + do_something + return if need_return? + end + end \ No newline at end of file diff --git a/config/contents/layout/empty_line_between_defs.md b/config/contents/layout/empty_line_between_defs.md index c3b150aa..7178e842 100644 --- a/config/contents/layout/empty_line_between_defs.md +++ b/config/contents/layout/empty_line_between_defs.md @@ -1,12 +1,12 @@ This cop checks whether method definitions are separated by one empty line. -`NumberOfEmptyLines` can be and integer (e.g. 1 by default) or -an array (e.g. [1, 2]) to specificy a minimum and a maximum of -empty lines. +`NumberOfEmptyLines` can be an integer (default is 1) or +an array (e.g. [1, 2]) to specify a minimum and maximum +number of empty lines permitted. -`AllowAdjacentOneLineDefs` can be used to configure is adjacent -one line methods definitions are an offense +`AllowAdjacentOneLineDefs` configures whether adjacent +one-line method definitions are considered an offense. ### Example: diff --git a/config/contents/layout/empty_lines.md b/config/contents/layout/empty_lines.md index b8b4d751..268015d8 100644 --- a/config/contents/layout/empty_lines.md +++ b/config/contents/layout/empty_lines.md @@ -1,4 +1,4 @@ -This cops checks for two or more consecutive blank lines. +This cop checks for two or more consecutive blank lines. ### Example: diff --git a/config/contents/layout/empty_lines_around_arguments.md b/config/contents/layout/empty_lines_around_arguments.md index d7a8a22d..8ebdbcc4 100644 --- a/config/contents/layout/empty_lines_around_arguments.md +++ b/config/contents/layout/empty_lines_around_arguments.md @@ -1,4 +1,4 @@ -This cops checks if empty lines exist around the arguments +This cop checks if empty lines exist around the arguments of a method invocation. ### Example: diff --git a/config/contents/layout/empty_lines_around_begin_body.md b/config/contents/layout/empty_lines_around_begin_body.md index 742ac0d6..31f8736b 100644 --- a/config/contents/layout/empty_lines_around_begin_body.md +++ b/config/contents/layout/empty_lines_around_begin_body.md @@ -1,4 +1,4 @@ -This cops checks if empty lines exist around the bodies of begin-end +This cop checks if empty lines exist around the bodies of begin-end blocks. ### Example: diff --git a/config/contents/layout/empty_lines_around_block_body.md b/config/contents/layout/empty_lines_around_block_body.md index 77cf3168..79120428 100644 --- a/config/contents/layout/empty_lines_around_block_body.md +++ b/config/contents/layout/empty_lines_around_block_body.md @@ -1,4 +1,4 @@ -This cops checks if empty lines around the bodies of blocks match +This cop checks if empty lines around the bodies of blocks match the configuration. ### Example: EnforcedStyle: empty_lines diff --git a/config/contents/layout/empty_lines_around_class_body.md b/config/contents/layout/empty_lines_around_class_body.md index 3bec0bca..7df1c154 100644 --- a/config/contents/layout/empty_lines_around_class_body.md +++ b/config/contents/layout/empty_lines_around_class_body.md @@ -1,4 +1,4 @@ -This cops checks if empty lines around the bodies of classes match +This cop checks if empty lines around the bodies of classes match the configuration. ### Example: EnforcedStyle: empty_lines @@ -31,6 +31,26 @@ the configuration. end +### Example: Enforcedstyle: beginning_only + # good + + class Foo + + def bar + # ... + end + end + +### Example: Enforcedstyle: ending_only + # good + + class Foo + def bar + # ... + end + + end + ### Example: EnforcedStyle: no_empty_lines (default) # good diff --git a/config/contents/layout/empty_lines_around_exception_handling_keywords.md b/config/contents/layout/empty_lines_around_exception_handling_keywords.md index 7b47f400..9933b3ba 100644 --- a/config/contents/layout/empty_lines_around_exception_handling_keywords.md +++ b/config/contents/layout/empty_lines_around_exception_handling_keywords.md @@ -1,4 +1,4 @@ -This cops checks if empty lines exist around the bodies of `begin` +This cop checks if empty lines exist around the bodies of `begin` sections. This cop doesn't check empty lines at `begin` body beginning/end and around method definition body. `Style/EmptyLinesAroundBeginBody` or `Style/EmptyLinesAroundMethodBody` diff --git a/config/contents/layout/empty_lines_around_method_body.md b/config/contents/layout/empty_lines_around_method_body.md index 4ba0275d..a096fd35 100644 --- a/config/contents/layout/empty_lines_around_method_body.md +++ b/config/contents/layout/empty_lines_around_method_body.md @@ -1,4 +1,4 @@ -This cops checks if empty lines exist around the bodies of methods. +This cop checks if empty lines exist around the bodies of methods. ### Example: diff --git a/config/contents/layout/empty_lines_around_module_body.md b/config/contents/layout/empty_lines_around_module_body.md index b2f40a14..9da03d84 100644 --- a/config/contents/layout/empty_lines_around_module_body.md +++ b/config/contents/layout/empty_lines_around_module_body.md @@ -1,4 +1,4 @@ -This cops checks if empty lines around the bodies of modules match +This cop checks if empty lines around the bodies of modules match the configuration. ### Example: EnforcedStyle: empty_lines diff --git a/config/contents/layout/end_alignment.md b/config/contents/layout/end_alignment.md new file mode 100644 index 00000000..3af4cf62 --- /dev/null +++ b/config/contents/layout/end_alignment.md @@ -0,0 +1,64 @@ +This cop checks whether the end keywords are aligned properly. + +Three modes are supported through the `EnforcedStyleAlignWith` +configuration parameter: + +If it's set to `keyword` (which is the default), the `end` +shall be aligned with the start of the keyword (if, class, etc.). + +If it's set to `variable` the `end` shall be aligned with the +left-hand-side of the variable assignment, if there is one. + +If it's set to `start_of_line`, the `end` shall be aligned with the +start of the line where the matching keyword appears. + +### Example: EnforcedStyleAlignWith: keyword (default) + # bad + + variable = if true + end + + # good + + variable = if true + end + + variable = + if true + end + +### Example: EnforcedStyleAlignWith: variable + # bad + + variable = if true + end + + # good + + variable = if true + end + + variable = + if true + end + +### Example: EnforcedStyleAlignWith: start_of_line + # bad + + variable = if true + end + + puts(if true + end) + + # good + + variable = if true + end + + puts(if true + end) + + variable = + if true + end \ No newline at end of file diff --git a/config/contents/layout/end_of_line.md b/config/contents/layout/end_of_line.md new file mode 100644 index 00000000..eb966a5e --- /dev/null +++ b/config/contents/layout/end_of_line.md @@ -0,0 +1,33 @@ +This cop checks for Windows-style line endings in the source code. + +### Example: EnforcedStyle: native (default) + # The `native` style means that CR+LF (Carriage Return + Line Feed) is + # enforced on Windows, and LF is enforced on other platforms. + + # bad + puts 'Hello' # Return character is LF on Windows. + puts 'Hello' # Return character is CR+LF on other than Windows. + + # good + puts 'Hello' # Return character is CR+LF on Windows. + puts 'Hello' # Return character is LF on other than Windows. + +### Example: EnforcedStyle: lf + # The `lf` style means that LF (Line Feed) is enforced on + # all platforms. + + # bad + puts 'Hello' # Return character is CR+LF on all platfoms. + + # good + puts 'Hello' # Return character is LF on all platfoms. + +### Example: EnforcedStyle: crlf + # The `crlf` style means that CR+LF (Carriage Return + Line Feed) is + # enforced on all platforms. + + # bad + puts 'Hello' # Return character is LF on all platfoms. + + # good + puts 'Hello' # Return character is CR+LF on all platfoms. diff --git a/config/contents/layout/extra_spacing.md b/config/contents/layout/extra_spacing.md index a9c73cdc..9dfcfcb7 100644 --- a/config/contents/layout/extra_spacing.md +++ b/config/contents/layout/extra_spacing.md @@ -6,9 +6,20 @@ This cop checks for extra/unnecessary whitespace. name = "RuboCop" # Some comment and an empty line - website += "/bbatsov/rubocop" unless cond + website += "/rubocop-hq/rubocop" unless cond puts "rubocop" if debug # bad for any configuration set_app("RuboCop") - website = "https://github.com/bbatsov/rubocop" \ No newline at end of file + website = "https://github.com/rubocop-hq/rubocop" + + # good only if AllowBeforeTrailingComments is true + object.method(arg) # this is a comment + + # good even if AllowBeforeTrailingComments is false or not set + object.method(arg) # this is a comment + + # good with either AllowBeforeTrailingComments or AllowForAlignment + object.method(arg) # this is a comment + another_object.method(arg) # this is another comment + some_object.method(arg) # this is some comment \ No newline at end of file diff --git a/config/contents/layout/heredoc_argument_closing_parenthesis.md b/config/contents/layout/heredoc_argument_closing_parenthesis.md new file mode 100644 index 00000000..1d03cdb0 --- /dev/null +++ b/config/contents/layout/heredoc_argument_closing_parenthesis.md @@ -0,0 +1,46 @@ +This cop checks for the placement of the closing parenthesis +in a method call that passes a HEREDOC string as an argument. +It should be placed at the end of the line containing the +opening HEREDOC tag. + +### Example: + # bad + + foo(<<-SQL + bar + SQL + ) + + foo(<<-SQL, 123, <<-NOSQL, + bar + SQL + baz + NOSQL + ) + + foo( + bar(<<-SQL + baz + SQL + ), + 123, + ) + + # good + + foo(<<-SQL) + bar + SQL + + foo(<<-SQL, 123, <<-NOSQL) + bar + SQL + baz + NOSQL + + foo( + bar(<<-SQL), + baz + SQL + 123, + ) diff --git a/config/contents/layout/indent_first_array_element.md b/config/contents/layout/indent_first_array_element.md new file mode 100644 index 00000000..2649cb28 --- /dev/null +++ b/config/contents/layout/indent_first_array_element.md @@ -0,0 +1,76 @@ +This cop checks the indentation of the first element in an array literal +where the opening bracket and the first element are on separate lines. +The other elements' indentations are handled by the AlignArray cop. + +By default, array literals that are arguments in a method call with +parentheses, and where the opening square bracket of the array is on the +same line as the opening parenthesis of the method call, shall have +their first element indented one step (two spaces) more than the +position inside the opening parenthesis. + +Other array literals shall have their first element indented one step +more than the start of the line where the opening square bracket is. + +This default style is called 'special_inside_parentheses'. Alternative +styles are 'consistent' and 'align_brackets'. Here are examples: + +### Example: EnforcedStyle: special_inside_parentheses (default) + # The `special_inside_parentheses` style enforces that the first + # element in an array literal where the opening bracket and first + # element are on seprate lines is indented one step (two spaces) more + # than the position inside the opening parenthesis. + + #bad + array = [ + :value + ] + and_in_a_method_call([ + :no_difference + ]) + + #good + array = [ + :value + ] + but_in_a_method_call([ + :its_like_this + ]) + +### Example: EnforcedStyle: consistent + # The `consistent` style enforces that the first element in an array + # literal where the opening bracket and the first element are on + # seprate lines is indented the same as an array literal which is not + # defined inside a method call. + + #bad + # consistent + array = [ + :value + ] + but_in_a_method_call([ + :its_like_this + ]) + + #good + array = [ + :value + ] + and_in_a_method_call([ + :no_difference + ]) + +### Example: EnforcedStyle: align_brackets + # The `align_brackets` style enforces that the opening and closing + # brackets are indented to the same position. + + #bad + # align_brackets + and_now_for_something = [ + :completely_different + ] + + #good + # align_brackets + and_now_for_something = [ + :completely_different + ] \ No newline at end of file diff --git a/config/contents/layout/indent_first_hash_element.md b/config/contents/layout/indent_first_hash_element.md new file mode 100644 index 00000000..083b97da --- /dev/null +++ b/config/contents/layout/indent_first_hash_element.md @@ -0,0 +1,74 @@ +This cop checks the indentation of the first key in a hash literal +where the opening brace and the first key are on separate lines. The +other keys' indentations are handled by the AlignHash cop. + +By default, Hash literals that are arguments in a method call with +parentheses, and where the opening curly brace of the hash is on the +same line as the opening parenthesis of the method call, shall have +their first key indented one step (two spaces) more than the position +inside the opening parenthesis. + +Other hash literals shall have their first key indented one step more +than the start of the line where the opening curly brace is. + +This default style is called 'special_inside_parentheses'. Alternative +styles are 'consistent' and 'align_braces'. Here are examples: + +### Example: EnforcedStyle: special_inside_parentheses (default) + # The `special_inside_parentheses` style enforces that the first key + # in a hash literal where the opening brace and the first key are on + # separate lines is indented one step (two spaces) more than the + # position inside the opening parentheses. + + # bad + hash = { + key: :value + } + and_in_a_method_call({ + no: :difference + }) + + # good + special_inside_parentheses + hash = { + key: :value + } + but_in_a_method_call({ + its_like: :this + }) + +### Example: EnforcedStyle: consistent + # The `consistent` style enforces that the first key in a hash + # literal where the opening brace and the first key are on + # separate lines is indented the same as a hash literal which is not + # defined inside a method call. + + # bad + hash = { + key: :value + } + but_in_a_method_call({ + its_like: :this + }) + + # good + hash = { + key: :value + } + and_in_a_method_call({ + no: :difference + }) + +### Example: EnforcedStyle: align_braces + # The `align_brackets` style enforces that the opening and closing + # braces are indented to the same position. + + # bad + and_now_for_something = { + completely: :different + } + + # good + and_now_for_something = { + completely: :different + } \ No newline at end of file diff --git a/config/contents/layout/indent_first_parameter.md b/config/contents/layout/indent_first_parameter.md new file mode 100644 index 00000000..5b8b2927 --- /dev/null +++ b/config/contents/layout/indent_first_parameter.md @@ -0,0 +1,34 @@ +This cop checks the indentation of the first parameter in a method call. +Parameters after the first one are checked by Layout/AlignParameters, +not by this cop. + +### Example: + + # bad + def some_method( + first_param, + second_param) + 123 + end + +### Example: EnforcedStyle: consistent + # The first parameter should always be indented one step more than the + # preceding line. + + # good + def some_method( + first_param, + second_param) + 123 + end + +### Example: EnforcedStyle: align_parentheses + # The first parameter should always be indented one step more than the + # opening parenthesis. + + # good + def some_method( + first_param, + second_param) + 123 + end \ No newline at end of file diff --git a/config/contents/layout/indent_heredoc.md b/config/contents/layout/indent_heredoc.md index e23f7367..d7679833 100644 --- a/config/contents/layout/indent_heredoc.md +++ b/config/contents/layout/indent_heredoc.md @@ -1,19 +1,37 @@ -This cops checks the indentation of the here document bodies. The bodies +This cop checks the indentation of the here document bodies. The bodies are indented one step. In Ruby 2.3 or newer, squiggly heredocs (`<<~`) should be used. If you use the older rubies, you should introduce some library to your project (e.g. ActiveSupport, Powerpack or Unindent). -Note: When `Metrics/LineLength`'s `AllowHeredoc` is false(not default), +Note: When `Metrics/LineLength`'s `AllowHeredoc` is false (not default), this cop does not add any offenses for long here documents to avoid `Metrics/LineLength`'s offenses. -### Example: - +### Example: EnforcedStyle: auto_detection (default) # bad <<-RUBY something RUBY + # good + # When using Ruby 2.3 or higher. + <<~RUBY + something + RUBY + + # good + # When using Ruby 2.2 or lower and enabled Rails department. + # The following is possible to enable Rails department by + # adding for example: + # + # Rails: + # Enabled: true + # + <<-RUBY.strip_heredoc + something + RUBY + +### Example: EnforcedStyle: squiggly # good # When EnforcedStyle is squiggly, bad code is auto-corrected to the # following code. @@ -21,9 +39,26 @@ Note: When `Metrics/LineLength`'s `AllowHeredoc` is false(not default), something RUBY +### Example: EnforcedStyle: active_support # good # When EnforcedStyle is active_support, bad code is auto-corrected to # the following code. <<-RUBY.strip_heredoc something - RUBY \ No newline at end of file + RUBY + +### Example: EnforcedStyle: powerpack + # good + # When EnforcedStyle is powerpack, bad code is auto-corrected to + # the following code. + <<-RUBY.strip_indent + something + RUBY + +### Example: EnforcedStyle: unindent + # good + # When EnforcedStyle is unindent, bad code is auto-corrected to + # the following code. + <<-RUBY.unindent + something + RUBY diff --git a/config/contents/layout/indentation_consistency.md b/config/contents/layout/indentation_consistency.md index 82c3b002..c74f276a 100644 --- a/config/contents/layout/indentation_consistency.md +++ b/config/contents/layout/indentation_consistency.md @@ -1,10 +1,114 @@ -This cops checks for inconsistent indentation. +This cop checks for inconsistent indentation. -### Example: +The difference between `rails` and `normal` is that the `rails` style +prescribes that in classes and modules the `protected` and `private` +modifier keywords shall be indented the same as public methods and that +protected and private members shall be indented one step more than the +modifiers. Other than that, both styles mean that entities on the same +logical depth shall have the same indentation. +### Example: EnforcedStyle: normal (default) + # bad class A def test puts 'hello' puts 'world' end + end + + # bad + class A + def test + puts 'hello' + puts 'world' + end + + protected + + def foo + end + + private + + def bar + end + end + + # good + class A + def test + puts 'hello' + puts 'world' + end + end + + # good + class A + def test + puts 'hello' + puts 'world' + end + + protected + + def foo + end + + private + + def bar + end + end + +### Example: EnforcedStyle: rails + # bad + class A + def test + puts 'hello' + puts 'world' + end + end + + # bad + class A + def test + puts 'hello' + puts 'world' + end + + protected + + def foo + end + + private + + def bar + end + end + + # good + class A + def test + puts 'hello' + puts 'world' + end + end + + # good + class A + def test + puts 'hello' + puts 'world' + end + + protected + + def foo + end + + private + + def bar + end end \ No newline at end of file diff --git a/config/contents/layout/indentation_width.md b/config/contents/layout/indentation_width.md index 8f8c6b1c..0aadfc49 100644 --- a/config/contents/layout/indentation_width.md +++ b/config/contents/layout/indentation_width.md @@ -1,4 +1,4 @@ -This cops checks for indentation that doesn't use the specified number +This cop checks for indentation that doesn't use the specified number of spaces. See also the IndentationConsistency cop which is the companion to this diff --git a/config/contents/layout/initial_indentation.md b/config/contents/layout/initial_indentation.md new file mode 100644 index 00000000..d74d08a2 --- /dev/null +++ b/config/contents/layout/initial_indentation.md @@ -0,0 +1,13 @@ +This cop checks for indentation of the first non-blank non-comment +line in a file. + +### Example: + # bad + class A + def foo; end + end + + # good + class A + def foo; end + end diff --git a/config/contents/layout/leading_blank_lines.md b/config/contents/layout/leading_blank_lines.md new file mode 100644 index 00000000..83b90ffc --- /dev/null +++ b/config/contents/layout/leading_blank_lines.md @@ -0,0 +1,24 @@ +This cop checks for unnecessary leading blank lines at the beginning +of a file. + +### Example: + + # bad + # (start of file) + + class Foo + end + + # bad + # (start of file) + + # a comment + + # good + # (start of file) + class Foo + end + + # good + # (start of file) + # a comment \ No newline at end of file diff --git a/config/contents/layout/multiline_array_brace_layout.md b/config/contents/layout/multiline_array_brace_layout.md index 8ae6e771..8c0a1b94 100644 --- a/config/contents/layout/multiline_array_brace_layout.md +++ b/config/contents/layout/multiline_array_brace_layout.md @@ -1,5 +1,5 @@ This cop checks that the closing brace in an array literal is either -on the same line as the last array element, or a new line. +on the same line as the last array element or on a new line. When using the `symmetrical` (default) style: diff --git a/config/contents/layout/multiline_array_line_breaks.md b/config/contents/layout/multiline_array_line_breaks.md new file mode 100644 index 00000000..4550b7c3 --- /dev/null +++ b/config/contents/layout/multiline_array_line_breaks.md @@ -0,0 +1,17 @@ +This cop ensures that each item in a multi-line array +starts on a separate line. + +### Example: + + # bad + [ + a, b, + c + ] + + # good + [ + a, + b, + c + ] \ No newline at end of file diff --git a/config/contents/layout/multiline_hash_key_line_breaks.md b/config/contents/layout/multiline_hash_key_line_breaks.md new file mode 100644 index 00000000..9da05489 --- /dev/null +++ b/config/contents/layout/multiline_hash_key_line_breaks.md @@ -0,0 +1,17 @@ +This cop ensures that each key in a multi-line hash +starts on a separate line. + +### Example: + + # bad + { + a: 1, b: 2, + c: 3 + } + + # good + { + a: 1, + b: 2, + c: 3 + } \ No newline at end of file diff --git a/config/contents/layout/multiline_method_argument_line_breaks.md b/config/contents/layout/multiline_method_argument_line_breaks.md new file mode 100644 index 00000000..b80dbb68 --- /dev/null +++ b/config/contents/layout/multiline_method_argument_line_breaks.md @@ -0,0 +1,16 @@ +This cop ensures that each argument in a multi-line method call +starts on a separate line. + +### Example: + + # bad + foo(a, b, + c + ) + + # good + foo( + a, + b, + c + ) \ No newline at end of file diff --git a/config/contents/layout/multiline_method_call_brace_layout.md b/config/contents/layout/multiline_method_call_brace_layout.md index 9a0bd593..9f695398 100644 --- a/config/contents/layout/multiline_method_call_brace_layout.md +++ b/config/contents/layout/multiline_method_call_brace_layout.md @@ -21,32 +21,65 @@ When using the `same_line` style: The closing brace of a multi-line method call must be on the same line as the last argument of the call. -### Example: - - # symmetrical: bad - # new_line: good - # same_line: bad - foo(a, - b - ) - - # symmetrical: bad - # new_line: bad - # same_line: good - foo( - a, - b) - - # symmetrical: good - # new_line: bad - # same_line: good - foo(a, - b) - - # symmetrical: good - # new_line: good - # same_line: bad - foo( - a, - b - ) \ No newline at end of file +### Example: EnforcedStyle: symmetrical (default) + # bad + foo(a, + b + ) + + # bad + foo( + a, + b) + + # good + foo(a, + b) + + # good + foo( + a, + b + ) + +### Example: EnforcedStyle: new_line + # bad + foo( + a, + b) + + # bad + foo(a, + b) + + # good + foo(a, + b + ) + + # good + foo( + a, + b + ) + +### Example: EnforcedStyle: same_line + # bad + foo(a, + b + ) + + # bad + foo( + a, + b + ) + + # good + foo( + a, + b) + + # good + foo(a, + b) \ No newline at end of file diff --git a/config/contents/layout/multiline_method_call_indentation.md b/config/contents/layout/multiline_method_call_indentation.md index add6c3f0..cde63232 100644 --- a/config/contents/layout/multiline_method_call_indentation.md +++ b/config/contents/layout/multiline_method_call_indentation.md @@ -1,7 +1,7 @@ This cop checks the indentation of the method name part in method calls that span more than one line. -### Example: EnforcedStyle: aligned +### Example: EnforcedStyle: aligned (default) # bad while myvariable .b diff --git a/config/contents/layout/multiline_method_definition_brace_layout.md b/config/contents/layout/multiline_method_definition_brace_layout.md index b390c935..3572739c 100644 --- a/config/contents/layout/multiline_method_definition_brace_layout.md +++ b/config/contents/layout/multiline_method_definition_brace_layout.md @@ -21,36 +21,77 @@ When using the `same_line` style: The closing brace of a multi-line method definition must be on the same line as the last parameter of the definition. -### Example: - - # symmetrical: bad - # new_line: good - # same_line: bad - def foo(a, - b - ) - end - - # symmetrical: bad - # new_line: bad - # same_line: good - def foo( - a, - b) - end - - # symmetrical: good - # new_line: bad - # same_line: good - def foo(a, - b) - end - - # symmetrical: good - # new_line: good - # same_line: bad - def foo( - a, - b - ) - end \ No newline at end of file +### Example: EnforcedStyle: symmetrical (default) + # bad + def foo(a, + b + ) + end + + # bad + def foo( + a, + b) + end + + # good + def foo(a, + b) + end + + # good + def foo( + a, + b + ) + end + +### Example: EnforcedStyle: new_line + # bad + def foo( + a, + b) + end + + # bad + def foo(a, + b) + end + + # good + def foo(a, + b + ) + end + + # good + def foo( + a, + b + ) + end + +### Example: EnforcedStyle: same_line + # bad + def foo(a, + b + ) + end + + # bad + def foo( + a, + b + ) + end + + # good + def foo( + a, + b) + end + + # good + def foo(a, + b) + end \ No newline at end of file diff --git a/config/contents/layout/multiline_operation_indentation.md b/config/contents/layout/multiline_operation_indentation.md index 9af39df0..a6430e5c 100644 --- a/config/contents/layout/multiline_operation_indentation.md +++ b/config/contents/layout/multiline_operation_indentation.md @@ -1,10 +1,10 @@ This cop checks the indentation of the right hand side operand in binary operations that span more than one line. -### Example: +### Example: EnforcedStyle: aligned (default) # bad if a + - b + b something end @@ -12,4 +12,17 @@ binary operations that span more than one line. if a + b something - end \ No newline at end of file + end + +### Example: EnforcedStyle: indented + # bad + if a + + b + something + end + + # good + if a + + b + something + end diff --git a/config/contents/layout/space_around_equals_in_parameter_default.md b/config/contents/layout/space_around_equals_in_parameter_default.md index 8eec9282..bfc5bd91 100644 --- a/config/contents/layout/space_around_equals_in_parameter_default.md +++ b/config/contents/layout/space_around_equals_in_parameter_default.md @@ -1,6 +1,7 @@ Checks that the equals signs in parameter default assignments have or don't have surrounding space depending on configuration. -### Example: + +### Example: EnforcedStyle: space (default) # bad def some_method(arg1=:default, arg2=nil, arg3=[]) # do something... @@ -9,4 +10,15 @@ have or don't have surrounding space depending on configuration. # good def some_method(arg1 = :default, arg2 = nil, arg3 = []) # do something... + end + +### Example: EnforcedStyle: no_space + # bad + def some_method(arg1 = :default, arg2 = nil, arg3 = []) + # do something... + end + + # good + def some_method(arg1=:default, arg2=nil, arg3=[]) + # do something... end \ No newline at end of file diff --git a/config/contents/layout/space_before_block_braces.md b/config/contents/layout/space_before_block_braces.md index a0dc9c14..d778560b 100644 --- a/config/contents/layout/space_before_block_braces.md +++ b/config/contents/layout/space_before_block_braces.md @@ -1,7 +1,7 @@ Checks that block braces have or don't have a space before the opening brace depending on configuration. -### Example: +### Example: EnforcedStyle: space (default) # bad foo.map{ |a| a.bar.to_s @@ -10,4 +10,15 @@ brace depending on configuration. # good foo.map { |a| a.bar.to_s + } + +### Example: EnforcedStyle: no_space + # bad + foo.map { |a| + a.bar.to_s + } + + # good + foo.map{ |a| + a.bar.to_s } \ No newline at end of file diff --git a/config/contents/layout/space_in_lambda_literal.md b/config/contents/layout/space_in_lambda_literal.md index d60382e2..d420fac4 100644 --- a/config/contents/layout/space_in_lambda_literal.md +++ b/config/contents/layout/space_in_lambda_literal.md @@ -1,5 +1,5 @@ -This cop checks for spaces between -> and opening parameter -brace in lambda literals. +This cop checks for spaces between `->` and opening parameter +parenthesis (`(`) in lambda literals. ### Example: EnforcedStyle: require_no_space (default) # bad diff --git a/config/contents/layout/space_inside_array_literal_brackets.md b/config/contents/layout/space_inside_array_literal_brackets.md index 8aca1b29..618ed7fd 100644 --- a/config/contents/layout/space_inside_array_literal_brackets.md +++ b/config/contents/layout/space_inside_array_literal_brackets.md @@ -11,7 +11,7 @@ surrounding space depending on configuration. # good array = [ a, b, c, d ] -### Example: EnforcedStyle: no_space +### Example: EnforcedStyle: no_space (default) # The `no_space` style enforces that array literals have # no surrounding space. @@ -28,6 +28,36 @@ surrounding space depending on configuration. # bad array = [ a, [ b, c ] ] + array = [ + [ a ], + [ b, c ] + ] # good - array = [ a, [ b, c ]] \ No newline at end of file + array = [ a, [ b, c ]] + array = [[ a ], + [ b, c ]] + +### Example: EnforcedStyleForEmptyBrackets: no_space (default) + # The `no_space` EnforcedStyleForEmptyBrackets style enforces that + # empty array brackets do not contain spaces. + + # bad + foo = [ ] + bar = [ ] + + # good + foo = [] + bar = [] + +### Example: EnforcedStyleForEmptyBrackets: space + # The `space` EnforcedStyleForEmptyBrackets style enforces that + # empty array brackets contain exactly one space. + + # bad + foo = [] + bar = [ ] + + # good + foo = [ ] + bar = [ ] diff --git a/config/contents/layout/space_inside_block_braces.md b/config/contents/layout/space_inside_block_braces.md index 10975fbe..6738f3eb 100644 --- a/config/contents/layout/space_inside_block_braces.md +++ b/config/contents/layout/space_inside_block_braces.md @@ -38,7 +38,7 @@ configuration. ### Example: EnforcedStyleForEmptyBraces: space # The `space` EnforcedStyleForEmptyBraces style enforces that - # block braces have at least a spece in between when empty. + # block braces have at least a space in between when empty. # bad some_array.each {} @@ -60,7 +60,7 @@ configuration. # good [1, 2, 3].each { |n| n * 2 } -### Example: SpaceBeforeBlockParameters: true +### Example: SpaceBeforeBlockParameters: false # The SpaceBeforeBlockParameters style set to `false` enforces that # there is no space between `{` and `|`. Overrides `EnforcedStyle` # if there is a conflict. diff --git a/config/contents/layout/space_inside_hash_literal_braces.md b/config/contents/layout/space_inside_hash_literal_braces.md index 566643cd..d9e48b24 100644 --- a/config/contents/layout/space_inside_hash_literal_braces.md +++ b/config/contents/layout/space_inside_hash_literal_braces.md @@ -1,7 +1,7 @@ Checks that braces used for hash literals have or don't have surrounding space depending on configuration. -### Example: EnforcedStyle: space +### Example: EnforcedStyle: space (default) # The `space` style enforces that hash literals have # surrounding space. @@ -28,6 +28,32 @@ surrounding space depending on configuration. # bad h = { a: { b: 2 } } + foo = { { a: 1 } => { b: { c: 2 } } } # good - h = { a: { b: 2 }} \ No newline at end of file + h = { a: { b: 2 }} + foo = {{ a: 1 } => { b: { c: 2 }}} + +### Example: EnforcedStyleForEmptyBraces: no_space (default) + # The `no_space` EnforcedStyleForEmptyBraces style enforces that + # empty hash braces do not contain spaces. + + # bad + foo = { } + bar = { } + + # good + foo = {} + bar = {} + +### Example: EnforcedStyleForEmptyBraces: space + # The `space` EnforcedStyleForEmptyBraces style enforces that + # empty hash braces contain space. + + # bad + foo = {} + + # good + foo = { } + foo = { } + foo = { } diff --git a/config/contents/layout/space_inside_parens.md b/config/contents/layout/space_inside_parens.md index 21342814..4ce52d6e 100644 --- a/config/contents/layout/space_inside_parens.md +++ b/config/contents/layout/space_inside_parens.md @@ -1,10 +1,27 @@ Checks for spaces inside ordinary round parentheses. -### Example: +### Example: EnforcedStyle: no_space (default) + # The `no_space` style enforces that parentheses do not have spaces. + # bad f( 3) g = (a + 3 ) # good f(3) - g = (a + 3) \ No newline at end of file + g = (a + 3) + +### Example: EnforcedStyle: space + # The `space` style enforces that parentheses have a space at the + # beginning and end. + # Note: Empty parentheses should not have spaces. + + # bad + f(3) + g = (a + 3) + y( ) + + # good + f( 3 ) + g = ( a + 3 ) + y() diff --git a/config/contents/layout/space_inside_reference_brackets.md b/config/contents/layout/space_inside_reference_brackets.md index d75ed237..8ee084ed 100644 --- a/config/contents/layout/space_inside_reference_brackets.md +++ b/config/contents/layout/space_inside_reference_brackets.md @@ -23,4 +23,27 @@ surrounding space depending on configuration. # good hash[ :key ] - array[ index ] \ No newline at end of file + array[ index ] + + +### Example: EnforcedStyleForEmptyBrackets: no_space (default) + # The `no_space` EnforcedStyleForEmptyBrackets style enforces that + # empty reference brackets do not contain spaces. + + # bad + foo[ ] + foo[ ] + + # good + foo[] + +### Example: EnforcedStyleForEmptyBrackets: space + # The `space` EnforcedStyleForEmptyBrackets style enforces that + # empty reference brackets contain exactly one space. + + # bad + foo[] + foo[ ] + + # good + foo[ ] diff --git a/config/contents/layout/tab.md b/config/contents/layout/tab.md new file mode 100644 index 00000000..ecca5491 --- /dev/null +++ b/config/contents/layout/tab.md @@ -0,0 +1,14 @@ +This cop checks for tabs inside the source code. + +### Example: + # bad + # This example uses a tab to indent bar. + def foo + bar + end + + # good + # This example uses spaces to indent bar. + def foo + bar + end diff --git a/config/contents/layout/trailing_blank_lines.md b/config/contents/layout/trailing_blank_lines.md new file mode 100644 index 00000000..913590a2 --- /dev/null +++ b/config/contents/layout/trailing_blank_lines.md @@ -0,0 +1,33 @@ +This cop looks for trailing blank lines and a final newline in the +source code. + +### Example: EnforcedStyle: final_blank_line + # `final_blank_line` looks for one blank line followed by a new line + # at the end of files. + + # bad + class Foo; end + # EOF + + # bad + class Foo; end # EOF + + # good + class Foo; end + + # EOF + +### Example: EnforcedStyle: final_newline (default) + # `final_newline` looks for one newline at the end of files. + + # bad + class Foo; end + + # EOF + + # bad + class Foo; end # EOF + + # good + class Foo; end + # EOF diff --git a/config/contents/layout/trailing_whitespace.md b/config/contents/layout/trailing_whitespace.md new file mode 100644 index 00000000..d2aa6cbb --- /dev/null +++ b/config/contents/layout/trailing_whitespace.md @@ -0,0 +1,10 @@ +This cop looks for trailing whitespace in the source code. + +### Example: + # The line in this example contains spaces after the 0. + # bad + x = 0 + + # The line in this example ends directly after the 0. + # good + x = 0 diff --git a/config/contents/lint/big_decimal_new.md b/config/contents/lint/big_decimal_new.md new file mode 100644 index 00000000..ff6a0326 --- /dev/null +++ b/config/contents/lint/big_decimal_new.md @@ -0,0 +1,10 @@ +`BigDecimal.new()` is deprecated since BigDecimal 1.3.3. +This cop identifies places where `BigDecimal.new()` +can be replaced by `BigDecimal()`. + +### Example: + # bad + BigDecimal.new(123.456, 3) + + # good + BigDecimal(123.456, 3) diff --git a/config/contents/lint/deprecated_class_methods.md b/config/contents/lint/deprecated_class_methods.md index 0ede887f..d365f906 100644 --- a/config/contents/lint/deprecated_class_methods.md +++ b/config/contents/lint/deprecated_class_methods.md @@ -5,9 +5,13 @@ This cop checks for uses of the deprecated class method usages. # bad File.exists?(some_path) + Dir.exists?(some_path) + iterator? ### Example: # good - File.exist?(some_path) \ No newline at end of file + File.exist?(some_path) + Dir.exist?(some_path) + block_given? \ No newline at end of file diff --git a/config/contents/lint/disjunctive_assignment_in_constructor.md b/config/contents/lint/disjunctive_assignment_in_constructor.md new file mode 100644 index 00000000..bc75f9a5 --- /dev/null +++ b/config/contents/lint/disjunctive_assignment_in_constructor.md @@ -0,0 +1,19 @@ +This cop checks constructors for disjunctive assignments that should +be plain assignments. + +So far, this cop is only concerned with disjunctive assignment of +instance variables. + +In ruby, an instance variable is nil until a value is assigned, so the +disjunction is unnecessary. A plain assignment has the same effect. + +### Example: + # bad + def initialize + @x ||= 1 + end + + # good + def initialize + @x = 1 + end \ No newline at end of file diff --git a/config/contents/lint/duplicate_methods.md b/config/contents/lint/duplicate_methods.md index a38d165e..ae8c942f 100644 --- a/config/contents/lint/duplicate_methods.md +++ b/config/contents/lint/duplicate_methods.md @@ -5,11 +5,11 @@ definitions. # bad - def duplicated + def foo 1 end - def duplicated + def foo 2 end @@ -17,20 +17,30 @@ definitions. # bad - def duplicated + def foo 1 end - alias duplicated other_duplicated + alias foo bar ### Example: # good - def duplicated + def foo 1 end - def other_duplicated + def bar 2 - end \ No newline at end of file + end + +### Example: + + # good + + def foo + 1 + end + + alias bar foo \ No newline at end of file diff --git a/config/contents/lint/ensure_return.md b/config/contents/lint/ensure_return.md index c155ed2e..4fdb2999 100644 --- a/config/contents/lint/ensure_return.md +++ b/config/contents/lint/ensure_return.md @@ -1,4 +1,7 @@ This cop checks for *return* from an *ensure* block. +Explicit return from an ensure block alters the control flow +as the return will take precedence over any exception being raised, +and the exception will be silently thrown away as if it were rescued. ### Example: diff --git a/config/contents/lint/erb_new_arguments.md b/config/contents/lint/erb_new_arguments.md new file mode 100644 index 00000000..12653336 --- /dev/null +++ b/config/contents/lint/erb_new_arguments.md @@ -0,0 +1,55 @@ + +This cop emulates the following Ruby warnings in Ruby 2.6. + +% cat example.rb +ERB.new('hi', nil, '-', '@output_buffer') +% ruby -rerb example.rb +example.rb:1: warning: Passing safe_level with the 2nd argument of +ERB.new is deprecated. Do not use it, and specify other arguments as +keyword arguments. +example.rb:1: warning: Passing trim_mode with the 3rd argument of +ERB.new is deprecated. Use keyword argument like +ERB.new(str, trim_mode:...) instead. +example.rb:1: warning: Passing eoutvar with the 4th argument of ERB.new +is deprecated. Use keyword argument like ERB.new(str, eoutvar: ...) +instead. + +Now non-keyword arguments other than first one are softly deprecated +and will be removed when Ruby 2.5 becomes EOL. +`ERB.new` with non-keyword arguments is deprecated since ERB 2.2.0. +Use `:trim_mode` and `:eoutvar` keyword arguments to `ERB.new`. +This cop identifies places where `ERB.new(str, trim_mode, eoutvar)` can +be replaced by `ERB.new(str, :trim_mode: trim_mode, eoutvar: eoutvar)`. + +### Example: + # Target codes supports Ruby 2.6 and higher only + # bad + ERB.new(str, nil, '-', '@output_buffer') + + # good + ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer') + + # Target codes supports Ruby 2.5 and lower only + # good + ERB.new(str, nil, '-', '@output_buffer') + + # Target codes supports Ruby 2.6, 2.5 and lower + # bad + ERB.new(str, nil, '-', '@output_buffer') + + # good + # Ruby standard library style + # https://github.com/ruby/ruby/commit/3406c5d + if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+ + ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer') + else + ERB.new(str, nil, '-', '@output_buffer') + end + + # good + # Use `RUBY_VERSION` style + if RUBY_VERSION >= '2.6' + ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer') + else + ERB.new(str, nil, '-', '@output_buffer') + end diff --git a/config/contents/lint/flip_flop.md b/config/contents/lint/flip_flop.md new file mode 100644 index 00000000..7011c2ea --- /dev/null +++ b/config/contents/lint/flip_flop.md @@ -0,0 +1,13 @@ +This cop looks for uses of flip-flop operator. +flip-flop operator is deprecated since Ruby 2.6.0. + +### Example: + # bad + (1..20).each do |x| + puts x if (x == 5) .. (x == 10) + end + + # good + (1..20).each do |x| + puts x if (x >= 5) && (x <= 10) + end \ No newline at end of file diff --git a/config/contents/lint/heredoc_method_call_position.md b/config/contents/lint/heredoc_method_call_position.md new file mode 100644 index 00000000..21b9a3c3 --- /dev/null +++ b/config/contents/lint/heredoc_method_call_position.md @@ -0,0 +1,26 @@ +This cop checks for the ordering of a method call where +the receiver of the call is a HEREDOC. + +### Example: + # bad + + <<-SQL + bar + SQL + .strip_indent + + <<-SQL + bar + SQL + .strip_indent + .trim + + # good + + <<-SQL.strip_indent + bar + SQL + + <<-SQL.strip_indent.trim + bar + SQL diff --git a/config/contents/lint/number_conversion.md b/config/contents/lint/number_conversion.md new file mode 100644 index 00000000..71e1f319 --- /dev/null +++ b/config/contents/lint/number_conversion.md @@ -0,0 +1,17 @@ +This cop warns the usage of unsafe number conversions. Unsafe +number conversion can cause unexpected error if auto type conversion +fails. Cop prefer parsing with number class instead. + +### Example: + + # bad + + '10'.to_i + '10.2'.to_f + '10'.to_c + + # good + + Integer('10', 10) + Float('10.2') + Complex('10') \ No newline at end of file diff --git a/config/contents/lint/ordered_magic_comments.md b/config/contents/lint/ordered_magic_comments.md new file mode 100644 index 00000000..c857fd41 --- /dev/null +++ b/config/contents/lint/ordered_magic_comments.md @@ -0,0 +1,23 @@ + +Checks the proper ordering of magic comments and whether +a magic comment is not placed before a shebang. + +### Example: + # bad + + # frozen_string_literal: true + # encoding: ascii + p [''.frozen?, ''.encoding] #=> [true, #] + + # good + + # encoding: ascii + # frozen_string_literal: true + p [''.frozen?, ''.encoding] #=> [true, #] + + # good + + #!/usr/bin/env ruby + # encoding: ascii + # frozen_string_literal: true + p [''.frozen?, ''.encoding] #=> [true, #] diff --git a/config/contents/lint/safe_navigation_chain.md b/config/contents/lint/safe_navigation_chain.md index d4ba8403..6feb81d2 100644 --- a/config/contents/lint/safe_navigation_chain.md +++ b/config/contents/lint/safe_navigation_chain.md @@ -1,6 +1,6 @@ The safe navigation operator returns nil if the receiver is -nil. If you chain an ordinary method call after a safe -navigation operator, it raises NoMethodError. We should use a +nil. If you chain an ordinary method call after a safe +navigation operator, it raises NoMethodError. We should use a safe navigation operator after a safe navigation operator. This cop checks for the problem outlined above. diff --git a/config/contents/lint/safe_navigation_consistency.md b/config/contents/lint/safe_navigation_consistency.md new file mode 100644 index 00000000..754ef793 --- /dev/null +++ b/config/contents/lint/safe_navigation_consistency.md @@ -0,0 +1,22 @@ +This cop check to make sure that if safe navigation is used for a method +call in an `&&` or `||` condition that safe navigation is used for all +method calls on that same object. + +### Example: + # bad + foo&.bar && foo.baz + + # bad + foo.bar || foo&.baz + + # bad + foo&.bar && (foobar.baz || foo.baz) + + # good + foo.bar && foo.baz + + # good + foo&.bar || foo&.baz + + # good + foo&.bar && (foobar.baz || foo&.baz) diff --git a/config/contents/lint/safe_navigation_with_empty.md b/config/contents/lint/safe_navigation_with_empty.md new file mode 100644 index 00000000..9f53375f --- /dev/null +++ b/config/contents/lint/safe_navigation_with_empty.md @@ -0,0 +1,15 @@ +This cop checks to make sure safe navigation isn't used with `empty?` in +a conditional. + +While the safe navigation operator is generally a good idea, when +checking `foo&.empty?` in a conditional, `foo` being `nil` will actually +do the opposite of what the author intends. + +### Example: + # bad + return if foo&.empty? + return unless foo&.empty? + + # good + return if foo && foo.empty? + return unless foo && foo.empty? diff --git a/config/contents/lint/script_permission.md b/config/contents/lint/script_permission.md new file mode 100644 index 00000000..afb90245 --- /dev/null +++ b/config/contents/lint/script_permission.md @@ -0,0 +1,26 @@ +This cop checks if a file which has a shebang line as +its first line is granted execute permission. + +### Example: + # bad + + # A file which has a shebang line as its first line is not + # granted execute permission. + + #!/usr/bin/env ruby + puts 'hello, world' + + # good + + # A file which has a shebang line as its first line is + # granted execute permission. + + #!/usr/bin/env ruby + puts 'hello, world' + + # good + + # A file which has not a shebang line as its first line is not + # granted execute permission. + + puts 'hello, world' diff --git a/config/contents/lint/shadowed_argument.md b/config/contents/lint/shadowed_argument.md index 1c6db3df..58e43a5d 100644 --- a/config/contents/lint/shadowed_argument.md +++ b/config/contents/lint/shadowed_argument.md @@ -1,9 +1,12 @@ This cop checks for shadowed arguments. +This cop has `IgnoreImplicitReferences` configuration option. +It means argument shadowing is used in order to pass parameters +to zero arity `super` when `IgnoreImplicitReferences` is `true`. + ### Example: # bad - do_something do |foo| foo = 42 puts foo @@ -14,10 +17,7 @@ This cop checks for shadowed arguments. puts foo end -### Example: - # good - do_something do |foo| foo = foo + 42 puts foo @@ -30,4 +30,30 @@ This cop checks for shadowed arguments. def do_something(foo) puts foo - end \ No newline at end of file + end + +### Example: IgnoreImplicitReferences: false (default) + + # bad + def do_something(foo) + foo = 42 + super + end + + def do_something(foo) + foo = super + bar + end + +### Example: IgnoreImplicitReferences: true + + # good + def do_something(foo) + foo = 42 + super + end + + def do_something(foo) + foo = super + bar + end diff --git a/config/contents/lint/syntax.md b/config/contents/lint/syntax.md new file mode 100644 index 00000000..e7faa93c --- /dev/null +++ b/config/contents/lint/syntax.md @@ -0,0 +1,3 @@ +This is not actually a cop. It does not inspect anything. It just +provides methods to repack Parser's diagnostics/errors +into RuboCop's offenses. \ No newline at end of file diff --git a/config/contents/lint/to_json.md b/config/contents/lint/to_json.md new file mode 100644 index 00000000..211507be --- /dev/null +++ b/config/contents/lint/to_json.md @@ -0,0 +1,13 @@ +This cop checks to make sure `#to_json` includes an optional argument. +When overriding `#to_json`, callers may invoke JSON +generation via `JSON.generate(your_obj)`. Since `JSON#generate` allows +for an optional argument, your method should too. + +### Example: + # bad + def to_json + end + + # good + def to_json(*_args) + end diff --git a/config/contents/lint/underscore_prefixed_variable_name.md b/config/contents/lint/underscore_prefixed_variable_name.md index a5a77a76..f01785da 100644 --- a/config/contents/lint/underscore_prefixed_variable_name.md +++ b/config/contents/lint/underscore_prefixed_variable_name.md @@ -1,7 +1,11 @@ This cop checks for underscore-prefixed variables that are actually used. -### Example: +Since block keyword arguments cannot be arbitrarily named at call +sites, the `AllowKeywordBlockArguments` will allow use of underscore- +prefixed block keyword arguments. + +### Example: AllowKeywordBlockArguments: false (default) # bad @@ -9,7 +13,9 @@ used. do_something(_num) end -### Example: + query(:sales) do |_id:, revenue:, cost:| + {_id: _id, profit: revenue - cost} + end # good @@ -17,10 +23,14 @@ used. do_something(num) end -### Example: + [1, 2, 3].each do |_num| + do_something # not using `_num` + end + +### Example: AllowKeywordBlockArguments: true # good - [1, 2, 3].each do |_num| - do_something # not using `_num` - end \ No newline at end of file + query(:sales) do |_id:, revenue:, cost:| + {_id: _id, profit: revenue - cost} + end diff --git a/config/contents/lint/unneeded_cop_disable_directive.md b/config/contents/lint/unneeded_cop_disable_directive.md new file mode 100644 index 00000000..4fc6aeb5 --- /dev/null +++ b/config/contents/lint/unneeded_cop_disable_directive.md @@ -0,0 +1,3 @@ +# The Lint/UnneededCopDisableDirective cop needs to be disabled so as +# to be able to provide a (bad) example of an unneeded disable. +# rubocop:disable Lint/UnneededCopDisableDirective \ No newline at end of file diff --git a/config/contents/lint/unneeded_cop_enable_directive.md b/config/contents/lint/unneeded_cop_enable_directive.md new file mode 100644 index 00000000..ae3bc8a4 --- /dev/null +++ b/config/contents/lint/unneeded_cop_enable_directive.md @@ -0,0 +1,3 @@ +# The Lint/UnneededCopEnableDirective cop needs to be disabled so as +# to be able to provide a (bad) example of an unneeded enable. +# rubocop:disable Lint/UnneededCopEnableDirective \ No newline at end of file diff --git a/config/contents/lint/unneeded_splat_expansion.md b/config/contents/lint/unneeded_splat_expansion.md index af4953f0..cc192824 100644 --- a/config/contents/lint/unneeded_splat_expansion.md +++ b/config/contents/lint/unneeded_splat_expansion.md @@ -39,7 +39,7 @@ This cop checks for unneeded usages of splat expansion end case foo - when *[1, 2, 3] + when 1, 2, 3 bar else baz diff --git a/config/contents/lint/uri_escape_unescape.md b/config/contents/lint/uri_escape_unescape.md index c8e6eb2d..a9550b51 100644 --- a/config/contents/lint/uri_escape_unescape.md +++ b/config/contents/lint/uri_escape_unescape.md @@ -1,9 +1,9 @@ This cop identifies places where `URI.escape` can be replaced by -`CGI.escape`, `URI.encode_www_form` or `URI.encode_www_form_component` +`CGI.escape`, `URI.encode_www_form`, or `URI.encode_www_form_component` depending on your specific use case. Also this cop identifies places where `URI.unescape` can be replaced by -`CGI.unescape`, `URI.decode_www_form` or `URI.decode_www_form_component` -depending on your specific use case. +`CGI.unescape`, `URI.decode_www_form`, +or `URI.decode_www_form_component` depending on your specific use case. ### Example: # bad diff --git a/config/contents/lint/void.md b/config/contents/lint/void.md index 816a07d7..43f5cd7a 100644 --- a/config/contents/lint/void.md +++ b/config/contents/lint/void.md @@ -1,5 +1,5 @@ -This cop checks for operators, variables and literals used -in void context. +This cop checks for operators, variables, literals, and nonmutating +methods used in void context. ### Example: @@ -19,6 +19,15 @@ in void context. do_something end +### Example: + + # bad, when CheckForMethodsWithNoSideEffects is set true + + def some_method(some_array) + some_array.sort + do_something(some_array) + end + ### Example: # good @@ -35,4 +44,13 @@ in void context. def some_method(some_var) do_something some_var + end + +### Example: + + # good, when CheckForMethodsWithNoSideEffects is set true + + def some_method(some_array) + some_array.sort! + do_something(some_array) end \ No newline at end of file diff --git a/config/contents/metrics/abc_size.md b/config/contents/metrics/abc_size.md index 5c7ed79b..ec4d7fea 100644 --- a/config/contents/metrics/abc_size.md +++ b/config/contents/metrics/abc_size.md @@ -1,3 +1,4 @@ This cop checks that the ABC size of methods is not higher than the configured maximum. The ABC size is based on assignments, branches -(method calls), and conditions. See http://c2.com/cgi/wiki?AbcMetric \ No newline at end of file +(method calls), and conditions. See http://c2.com/cgi/wiki?AbcMetric +and https://en.wikipedia.org/wiki/ABC_Software_Metric. \ No newline at end of file diff --git a/config/contents/naming/class_and_module_camel_case.md b/config/contents/naming/class_and_module_camel_case.md index 4c7a0045..ffd76dd5 100644 --- a/config/contents/naming/class_and_module_camel_case.md +++ b/config/contents/naming/class_and_module_camel_case.md @@ -1,4 +1,4 @@ -This cops checks for class and module names with +This cop checks for class and module names with an underscore in them. ### Example: diff --git a/config/contents/naming/file_name.md b/config/contents/naming/file_name.md index ef41a0cb..b6b9e260 100644 --- a/config/contents/naming/file_name.md +++ b/config/contents/naming/file_name.md @@ -2,6 +2,11 @@ This cop makes sure that Ruby source files have snake_case names. Ruby scripts (i.e. source files with a shebang in the first line) are ignored. +The cop also ignores `.gemspec` files, because Bundler +recommends using dashes to separate namespaces in nested gems +(i.e. `bundler-console` becomes `Bundler::Console`). As such, the +gemspec is supposed to be named `bundler-console.gemspec`. + ### Example: # bad lib/layoutManager.rb diff --git a/config/contents/naming/memoized_instance_variable_name.md b/config/contents/naming/memoized_instance_variable_name.md new file mode 100644 index 00000000..563199e3 --- /dev/null +++ b/config/contents/naming/memoized_instance_variable_name.md @@ -0,0 +1,81 @@ +This cop checks for memoized methods whose instance variable name +does not match the method name. + +This cop can be configured with the EnforcedStyleForLeadingUnderscores +directive. It can be configured to allow for memoized instance variables +prefixed with an underscore. Prefixing ivars with an underscore is a +convention that is used to implicitly indicate that an ivar should not +be set or referencd outside of the memoization method. + +### Example: EnforcedStyleForLeadingUnderscores: disallowed (default) + # bad + # Method foo is memoized using an instance variable that is + # not `@foo`. This can cause confusion and bugs. + def foo + @something ||= calculate_expensive_thing + end + + # good + def _foo + @foo ||= calculate_expensive_thing + end + + # good + def foo + @foo ||= calculate_expensive_thing + end + + # good + def foo + @foo ||= begin + calculate_expensive_thing + end + end + + # good + def foo + helper_variable = something_we_need_to_calculate_foo + @foo ||= calculate_expensive_thing(helper_variable) + end + +### Example: EnforcedStyleForLeadingUnderscores: required + # bad + def foo + @something ||= calculate_expensive_thing + end + + # bad + def foo + @foo ||= calculate_expensive_thing + end + + # good + def foo + @_foo ||= calculate_expensive_thing + end + + # good + def _foo + @_foo ||= calculate_expensive_thing + end + +### Example: EnforcedStyleForLeadingUnderscores :optional + # bad + def foo + @something ||= calculate_expensive_thing + end + + # good + def foo + @foo ||= calculate_expensive_thing + end + + # good + def foo + @_foo ||= calculate_expensive_thing + end + + # good + def _foo + @_foo ||= calculate_expensive_thing + end \ No newline at end of file diff --git a/config/contents/naming/predicate_name.md b/config/contents/naming/predicate_name.md index ca482bbd..07a2d0cc 100644 --- a/config/contents/naming/predicate_name.md +++ b/config/contents/naming/predicate_name.md @@ -2,6 +2,9 @@ This cop makes sure that predicates are named properly. ### Example: # bad + def is_even(value) + end + def is_even?(value) end @@ -10,6 +13,9 @@ This cop makes sure that predicates are named properly. end # bad + def has_value + end + def has_value? end diff --git a/config/contents/naming/rescued_exceptions_variable_name.md b/config/contents/naming/rescued_exceptions_variable_name.md new file mode 100644 index 00000000..13b44434 --- /dev/null +++ b/config/contents/naming/rescued_exceptions_variable_name.md @@ -0,0 +1,49 @@ +This cop makes sure that rescued exceptions variables are named as +expected. + +The `PreferredName` config option takes a `String`. It represents +the required name of the variable. Its default is `e`. + +### Example: PreferredName: e (default) + # bad + begin + # do something + rescue MyException => exception + # do something + end + + # good + begin + # do something + rescue MyException => e + # do something + end + + # good + begin + # do something + rescue MyException => _e + # do something + end + +### Example: PreferredName: exception + # bad + begin + # do something + rescue MyException => e + # do something + end + + # good + begin + # do something + rescue MyException => exception + # do something + end + + # good + begin + # do something + rescue MyException => _exception + # do something + end diff --git a/config/contents/naming/uncommunicative_block_param_name.md b/config/contents/naming/uncommunicative_block_param_name.md new file mode 100644 index 00000000..f7ea8503 --- /dev/null +++ b/config/contents/naming/uncommunicative_block_param_name.md @@ -0,0 +1,32 @@ +This cop checks block parameter names for how descriptive they +are. It is highly configurable. + +The `MinNameLength` config option takes an integer. It represents +the minimum amount of characters the name must be. Its default is 1. +The `AllowNamesEndingInNumbers` config option takes a boolean. When +set to false, this cop will register offenses for names ending with +numbers. Its default is false. The `AllowedNames` config option +takes an array of whitelisted names that will never register an +offense. The `ForbiddenNames` config option takes an array of +blacklisted names that will always register an offense. + +### Example: + # bad + bar do |varOne, varTwo| + varOne + varTwo + end + + # With `AllowNamesEndingInNumbers` set to false + foo { |num1, num2| num1 * num2 } + + # With `MinParamNameLength` set to number greater than 1 + baz { |a, b, c| do_stuff(a, b, c) } + + # good + bar do |thud, fred| + thud + fred + end + + foo { |speed, distance| speed * distance } + + baz { |age, height, gender| do_stuff(age, height, gender) } \ No newline at end of file diff --git a/config/contents/naming/uncommunicative_method_param_name.md b/config/contents/naming/uncommunicative_method_param_name.md new file mode 100644 index 00000000..cca06e48 --- /dev/null +++ b/config/contents/naming/uncommunicative_method_param_name.md @@ -0,0 +1,40 @@ +This cop checks method parameter names for how descriptive they +are. It is highly configurable. + +The `MinNameLength` config option takes an integer. It represents +the minimum amount of characters the name must be. Its default is 3. +The `AllowNamesEndingInNumbers` config option takes a boolean. When +set to false, this cop will register offenses for names ending with +numbers. Its default is false. The `AllowedNames` config option +takes an array of whitelisted names that will never register an +offense. The `ForbiddenNames` config option takes an array of +blacklisted names that will always register an offense. + +### Example: + # bad + def bar(varOne, varTwo) + varOne + varTwo + end + + # With `AllowNamesEndingInNumbers` set to false + def foo(num1, num2) + num1 * num2 + end + + # With `MinArgNameLength` set to number greater than 1 + def baz(a, b, c) + do_stuff(a, b, c) + end + + # good + def bar(thud, fred) + thud + fred + end + + def foo(speed, distance) + speed * distance + end + + def baz(age_a, height_b, gender_c) + do_stuff(age_a, height_b, gender_c) + end \ No newline at end of file diff --git a/config/contents/naming/variable_number.md b/config/contents/naming/variable_number.md index a3b0e735..4eb12b8c 100644 --- a/config/contents/naming/variable_number.md +++ b/config/contents/naming/variable_number.md @@ -1,5 +1,5 @@ This cop makes sure that all numbered variables use the -configured style, snake_case, normalcase or non_integer, +configured style, snake_case, normalcase, or non_integer, for their numbering. ### Example: EnforcedStyle: snake_case diff --git a/config/contents/rails/active_record_aliases.md b/config/contents/rails/active_record_aliases.md new file mode 100644 index 00000000..dcbd40ba --- /dev/null +++ b/config/contents/rails/active_record_aliases.md @@ -0,0 +1,9 @@ +Checks that ActiveRecord aliases are not used. The direct method names +are more clear and easier to read. + +### Example: + #bad + Book.update_attributes!(author: 'Alice') + + #good + Book.update!(author: 'Alice') \ No newline at end of file diff --git a/config/contents/rails/active_record_override.md b/config/contents/rails/active_record_override.md new file mode 100644 index 00000000..df768a71 --- /dev/null +++ b/config/contents/rails/active_record_override.md @@ -0,0 +1,20 @@ +Checks for overriding built-in Active Record methods instead of using +callbacks. + +### Example: + # bad + class Book < ApplicationRecord + def save + self.title = title.upcase! + super + end + end + + # good + class Book < ApplicationRecord + before_save :upcase_title + + def upcase_title + self.title = title.upcase! + end + end diff --git a/config/contents/rails/assert_not.md b/config/contents/rails/assert_not.md new file mode 100644 index 00000000..a3ec5a9a --- /dev/null +++ b/config/contents/rails/assert_not.md @@ -0,0 +1,9 @@ + +Use `assert_not` instead of `assert !`. + +### Example: + # bad + assert !x + + # good + assert_not x diff --git a/config/contents/rails/belongs_to.md b/config/contents/rails/belongs_to.md new file mode 100644 index 00000000..71cbcf74 --- /dev/null +++ b/config/contents/rails/belongs_to.md @@ -0,0 +1,47 @@ +This cop looks for belongs_to associations where we control whether the +association is required via the deprecated `required` option instead. + +Since Rails 5, belongs_to associations are required by default and this +can be controlled through the use of `optional: true`. + +From the release notes: + + belongs_to will now trigger a validation error by default if the + association is not present. You can turn this off on a + per-association basis with optional: true. Also deprecate required + option in favor of optional for belongs_to. (Pull Request) + +In the case that the developer is doing `required: false`, we +definitely want to autocorrect to `optional: true`. + +However, without knowing whether they've set overridden the default +value of `config.active_record.belongs_to_required_by_default`, we +can't say whether it's safe to remove `required: true` or whether we +should replace it with `optional: false` (or, similarly, remove a +superfluous `optional: false`). Therefore, in the cases we're using +`required: true`, we'll simply invert it to `optional: false` and the +user can remove depending on their defaults. + +### Example: + # bad + class Post < ApplicationRecord + belongs_to :blog, required: false + end + + # good + class Post < ApplicationRecord + belongs_to :blog, optional: true + end + + # bad + class Post < ApplicationRecord + belongs_to :blog, required: true + end + + # good + class Post < ApplicationRecord + belongs_to :blog, optional: false + end + +@see https://guides.rubyonrails.org/5_0_release_notes.html +@see https://github.com/rails/rails/pull/18937 \ No newline at end of file diff --git a/config/contents/rails/blank.md b/config/contents/rails/blank.md index 96dc9c0a..1938164e 100644 --- a/config/contents/rails/blank.md +++ b/config/contents/rails/blank.md @@ -1,34 +1,50 @@ -This cops checks for code that can be changed to `blank?`. -Settings: - NilOrEmpty: Convert checks for `nil` or `empty?` to `blank?` - NotPresent: Convert usages of not `present?` to `blank?` - UnlessPresent: Convert usages of `unless` `present?` to `blank?` - -### Example: - # NilOrEmpty: true - # bad - foo.nil? || foo.empty? - foo == nil || foo.empty? - - # good - foo.blank? - - # NotPresent: true - # bad - !foo.present? - - # good - foo.blank? - - # UnlessPresent: true - # bad - something unless foo.present? - unless foo.present? - something - end - - # good - something if foo.blank? - if foo.blank? - something - end \ No newline at end of file +This cop checks for code that can be written with simpler conditionals +using `Object#blank?` defined by Active Support. + +Interaction with `Style/UnlessElse`: +The configuration of `NotPresent` will not produce an offense in the +context of `unless else` if `Style/UnlessElse` is inabled. This is +to prevent interference between the auto-correction of the two cops. + +### Example: NilOrEmpty: true (default) + # Converts usages of `nil? || empty?` to `blank?` + + # bad + foo.nil? || foo.empty? + foo == nil || foo.empty? + + # good + foo.blank? + +### Example: NotPresent: true (default) + # Converts usages of `!present?` to `blank?` + + # bad + !foo.present? + + # good + foo.blank? + +### Example: UnlessPresent: true (default) + # Converts usages of `unless present?` to `if blank?` + + # bad + something unless foo.present? + + # good + something if foo.blank? + + # bad + unless foo.present? + something + end + + # good + if foo.blank? + something + end + + # good + def blank? + !present? + end \ No newline at end of file diff --git a/config/contents/rails/bulk_change_table.md b/config/contents/rails/bulk_change_table.md new file mode 100644 index 00000000..715f18ff --- /dev/null +++ b/config/contents/rails/bulk_change_table.md @@ -0,0 +1,62 @@ +This Cop checks whether alter queries are combinable. +If combinable queries are detected, it suggests to you +to use `change_table` with `bulk: true` instead. +This option causes the migration to generate a single +ALTER TABLE statement combining multiple column alterations. + +The `bulk` option is only supported on the MySQL and +the PostgreSQL (5.2 later) adapter; thus it will +automatically detect an adapter from `development` environment +in `config/database.yml` when the `Database` option is not set. +If the adapter is not `mysql2` or `postgresql`, +this Cop ignores offenses. + +### Example: + # bad + def change + add_column :users, :name, :string, null: false + add_column :users, :nickname, :string + + # ALTER TABLE `users` ADD `name` varchar(255) NOT NULL + # ALTER TABLE `users` ADD `nickname` varchar(255) + end + + # good + def change + change_table :users, bulk: true do |t| + t.string :name, null: false + t.string :nickname + end + + # ALTER TABLE `users` ADD `name` varchar(255) NOT NULL, + # ADD `nickname` varchar(255) + end + +### Example: + # bad + def change + change_table :users do |t| + t.string :name, null: false + t.string :nickname + end + end + + # good + def change + change_table :users, bulk: true do |t| + t.string :name, null: false + t.string :nickname + end + end + + # good + # When you don't want to combine alter queries. + def change + change_table :users, bulk: false do |t| + t.string :name, null: false + t.string :nickname + end + end + +@see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-change_table +@see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html \ No newline at end of file diff --git a/config/contents/rails/date.md b/config/contents/rails/date.md index d75472d2..0aba40e3 100644 --- a/config/contents/rails/date.md +++ b/config/contents/rails/date.md @@ -1,19 +1,19 @@ This cop checks for the correct use of Date methods, such as Date.today, Date.current etc. -Using Date.today is dangerous, because it doesn't know anything about -Rails time zone. You must use Time.zone.today instead. +Using `Date.today` is dangerous, because it doesn't know anything about +Rails time zone. You must use `Time.zone.today` instead. -The cop also reports warnings when you are using 'to_time' method, +The cop also reports warnings when you are using `to_time` method, because it doesn't know about Rails time zone either. Two styles are supported for this cop. When EnforcedStyle is 'strict' -then the Date methods (today, current, yesterday, tomorrow) -are prohibited and the usage of both 'to_time' -and 'to_time_in_current_zone' is reported as warning. +then the Date methods `today`, `current`, `yesterday`, and `tomorrow` +are prohibited and the usage of both `to_time` +and 'to_time_in_current_zone' are reported as warning. -When EnforcedStyle is 'flexible' then only 'Date.today' is prohibited -and only 'to_time' is reported as warning. +When EnforcedStyle is 'flexible' then only `Date.today` is prohibited +and only `to_time` is reported as warning. ### Example: EnforcedStyle: strict # bad @@ -21,7 +21,6 @@ and only 'to_time' is reported as warning. Date.yesterday Date.today date.to_time - date.to_time_in_current_zone # good Time.zone.today @@ -37,4 +36,4 @@ and only 'to_time' is reported as warning. Time.zone.today - 1.day Date.current Date.yesterday - date.to_time_in_current_zone + date.in_time_zone diff --git a/config/contents/rails/delegate.md b/config/contents/rails/delegate.md index 3fdb58c3..5b6e85dd 100644 --- a/config/contents/rails/delegate.md +++ b/config/contents/rails/delegate.md @@ -30,7 +30,7 @@ When set to `false`, this case is legal. foo.bar end - # EnforceForPrefixed: true +### Example: EnforceForPrefixed: true (default) # bad def foo_bar foo.bar @@ -39,7 +39,7 @@ When set to `false`, this case is legal. # good delegate :bar, to: :foo, prefix: true - # EnforceForPrefixed: false +### Example: EnforceForPrefixed: false # good def foo_bar foo.bar diff --git a/config/contents/rails/dynamic_find_by.md b/config/contents/rails/dynamic_find_by.md index 73d9621c..366f77dd 100644 --- a/config/contents/rails/dynamic_find_by.md +++ b/config/contents/rails/dynamic_find_by.md @@ -1,6 +1,6 @@ This cop checks dynamic `find_by_*` methods. Use `find_by` instead of dynamic method. -See. https://github.com/bbatsov/rails-style-guide#find_by +See. https://github.com/rubocop-hq/rails-style-guide#find_by ### Example: # bad diff --git a/config/contents/rails/exit.md b/config/contents/rails/exit.md index 46c4d73c..524901c3 100644 --- a/config/contents/rails/exit.md +++ b/config/contents/rails/exit.md @@ -1,12 +1,12 @@ -This cop enforces that 'exit' calls are not used within a rails app. -Valid options are instead to raise an error, break, return or some +This cop enforces that `exit` calls are not used within a rails app. +Valid options are instead to raise an error, break, return, or some other form of stopping execution of current request. -There are two obvious cases where 'exit' is particularly harmful: +There are two obvious cases where `exit` is particularly harmful: -- Usage in library code for your application. Even though rails will -rescue from a SystemExit and continue on, unit testing that library -code will result in specs exiting (potentially silently if exit(0) +- Usage in library code for your application. Even though Rails will +rescue from a `SystemExit` and continue on, unit testing that library +code will result in specs exiting (potentially silently if `exit(0)` is used.) - Usage in application code outside of the web process could result in the program exiting, which could result in the code failing to run and diff --git a/config/contents/rails/file_path.md b/config/contents/rails/file_path.md index 399cc86a..7427765f 100644 --- a/config/contents/rails/file_path.md +++ b/config/contents/rails/file_path.md @@ -1,11 +1,21 @@ This cop is used to identify usages of file path joining process -to use `Rails.root.join` clause. +to use `Rails.root.join` clause. It is used to add uniformity when +joining paths. -### Example: - # bad - Rails.root.join('app/models/goober') - File.join(Rails.root, 'app/models/goober') - "#{Rails.root}/app/models/goober" +### Example: EnforcedStyle: arguments (default) + # bad + Rails.root.join('app/models/goober') + File.join(Rails.root, 'app/models/goober') + "#{Rails.root}/app/models/goober" - # good - Rails.root.join('app', 'models', 'goober') \ No newline at end of file + # good + Rails.root.join('app', 'models', 'goober') + +### Example: EnforcedStyle: slashes + # bad + Rails.root.join('app', 'models', 'goober') + File.join(Rails.root, 'app/models/goober') + "#{Rails.root}/app/models/goober" + + # good + Rails.root.join('app/models/goober') diff --git a/config/contents/rails/http_positional_arguments.md b/config/contents/rails/http_positional_arguments.md index c3676a5f..55feff47 100644 --- a/config/contents/rails/http_positional_arguments.md +++ b/config/contents/rails/http_positional_arguments.md @@ -1,6 +1,6 @@ This cop is used to identify usages of http methods like `get`, `post`, `put`, `patch` without the usage of keyword arguments in your tests and -change them to use keyword args. This cop only applies to Rails >= 5 . +change them to use keyword args. This cop only applies to Rails >= 5. If you are running Rails < 5 you should disable the Rails/HttpPositionalArguments cop or set your TargetRailsVersion in your .rubocop.yml file to 4.0, etc. diff --git a/config/contents/rails/http_status.md b/config/contents/rails/http_status.md new file mode 100644 index 00000000..1503e282 --- /dev/null +++ b/config/contents/rails/http_status.md @@ -0,0 +1,27 @@ +Enforces use of symbolic or numeric value to define HTTP status. + +### Example: EnforcedStyle: symbolic (default) + # bad + render :foo, status: 200 + render json: { foo: 'bar' }, status: 200 + render plain: 'foo/bar', status: 304 + redirect_to root_url, status: 301 + + # good + render :foo, status: :ok + render json: { foo: 'bar' }, status: :ok + render plain: 'foo/bar', status: :not_modified + redirect_to root_url, status: :moved_permanently + +### Example: EnforcedStyle: numeric + # bad + render :foo, status: :ok + render json: { foo: 'bar' }, status: :not_found + render plain: 'foo/bar', status: :not_modified + redirect_to root_url, status: :moved_permanently + + # good + render :foo, status: 200 + render json: { foo: 'bar' }, status: 404 + render plain: 'foo/bar', status: 304 + redirect_to root_url, status: 301 diff --git a/config/contents/rails/ignored_skip_action_filter_option.md b/config/contents/rails/ignored_skip_action_filter_option.md new file mode 100644 index 00000000..bac1b369 --- /dev/null +++ b/config/contents/rails/ignored_skip_action_filter_option.md @@ -0,0 +1,34 @@ +This cop checks that `if` and `only` (or `except`) are not used together +as options of `skip_*` action filter. + +The `if` option will be ignored when `if` and `only` are used together. +Similarly, the `except` option will be ignored when `if` and `except` +are used together. + +### Example: + # bad + class MyPageController < ApplicationController + skip_before_action :login_required, + only: :show, if: :trusted_origin? + end + + # good + class MyPageController < ApplicationController + skip_before_action :login_required, + if: -> { trusted_origin? && action_name == "show" } + end + +### Example: + # bad + class MyPageController < ApplicationController + skip_before_action :login_required, + except: :admin, if: :trusted_origin? + end + + # good + class MyPageController < ApplicationController + skip_before_action :login_required, + if: -> { trusted_origin? && action_name != "admin" } + end + +@see https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options \ No newline at end of file diff --git a/config/contents/rails/inverse_of.md b/config/contents/rails/inverse_of.md index dc64ae6b..0ca5669a 100644 --- a/config/contents/rails/inverse_of.md +++ b/config/contents/rails/inverse_of.md @@ -1,8 +1,14 @@ This cop looks for has_(one|many) and belongs_to associations where -ActiveRecord can't automatically determine the inverse association -because of a scope or the options used. This can result in unnecessary -queries in some circumstances. `:inverse_of` must be manually specified -for associations to work in both ways, or set to `false` to opt-out. +Active Record can't automatically determine the inverse association +because of a scope or the options used. Using the blog with order scope +example below, traversing the a Blog's association in both directions +with `blog.posts.first.blog` would cause the `blog` to be loaded from +the database twice. + +`:inverse_of` must be manually specified for Active Record to use the +associated object in memory, or set to `false` to opt-out. Note that +setting `nil` does not stop Active Record from trying to determine the +inverse automatically, and is not considered a valid value for this. ### Example: # good @@ -27,9 +33,8 @@ for associations to work in both ways, or set to `false` to opt-out. # good class Blog < ApplicationRecord has_many(:posts, - -> { order(published_at: :desc) }, - inverse_of: :blog - ) + -> { order(published_at: :desc) }, + inverse_of: :blog) end class Post < ApplicationRecord @@ -47,6 +52,14 @@ for associations to work in both ways, or set to `false` to opt-out. belongs_to :blog end + # good + # When you don't want to use the inverse association. + class Blog < ApplicationRecord + has_many(:posts, + -> { order(published_at: :desc) }, + inverse_of: false) + end + ### Example: # bad class Picture < ApplicationRecord @@ -108,5 +121,5 @@ for associations to work in both ways, or set to `false` to opt-out. has_many :physicians, through: :appointments end -@see http://guides.rubyonrails.org/association_basics.html#bi-directional-associations -@see http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses \ No newline at end of file +@see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations +@see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses \ No newline at end of file diff --git a/config/contents/rails/lexically_scoped_action_filter.md b/config/contents/rails/lexically_scoped_action_filter.md index d24185f7..27a35143 100644 --- a/config/contents/rails/lexically_scoped_action_filter.md +++ b/config/contents/rails/lexically_scoped_action_filter.md @@ -1,10 +1,13 @@ -This cop checks that methods specified in the filter's `only` -or `except` options are explicitly defined in the controller. +This cop checks that methods specified in the filter's `only` or +`except` options are defined within the same class or module. -You can specify methods of superclass or methods added by mixins -on the filter, but these confuse developers. If you specify methods -where are defined on another controller, you should define the filter -in that controller. +You can technically specify methods of superclass or methods added by +mixins on the filter, but these can confuse developers. If you specify +methods that are defined in other classes or modules, you should +define the filter in that class or module. + +If you rely on behaviour defined in the superclass actions, you must +remember to invoke `super` in the subclass actions. ### Example: # bad @@ -27,4 +30,50 @@ in that controller. def logout end + end + +### Example: + # bad + module FooMixin + extend ActiveSupport::Concern + + included do + before_action proc { authenticate }, only: :foo + end + end + + # good + module FooMixin + extend ActiveSupport::Concern + + included do + before_action proc { authenticate }, only: :foo + end + + def foo + # something + end + end + +### Example: + class ContentController < ApplicationController + def update + @content.update(content_attributes) + end + end + + class ArticlesController < ContentController + before_action :load_article, only: [:update] + + # the cop requires this method, but it relies on behaviour defined + # in the superclass, so needs to invoke `super` + def update + super + end + + private + + def load_article + @content = Article.find(params[:article_id]) + end end \ No newline at end of file diff --git a/config/contents/rails/link_to_blank.md b/config/contents/rails/link_to_blank.md new file mode 100644 index 00000000..babf5148 --- /dev/null +++ b/config/contents/rails/link_to_blank.md @@ -0,0 +1,11 @@ +This cop checks for calls to `link_to` that contain a +`target: '_blank'` but no `rel: 'noopener'`. This can be a security +risk as the loaded page will have control over the previous page +and could change its location for phishing purposes. + +### Example: + # bad + link_to 'Click here', url, target: '_blank' + + # good + link_to 'Click here', url, target: '_blank', rel: 'noopener' \ No newline at end of file diff --git a/config/contents/rails/output_safety.md b/config/contents/rails/output_safety.md index bc4da1bb..653bdbd9 100644 --- a/config/contents/rails/output_safety.md +++ b/config/contents/rails/output_safety.md @@ -1,7 +1,7 @@ -This cop checks for the use of output safety calls like html_safe, -raw, and safe_concat. These methods do not escape content. They +This cop checks for the use of output safety calls like `html_safe`, +`raw`, and `safe_concat`. These methods do not escape content. They simply return a SafeBuffer containing the content as is. Instead, -use safe_join to join content and escape it and concat to +use `safe_join` to join content and escape it and concat to concatenate content and escape it, ensuring its safety. ### Example: diff --git a/config/contents/rails/present.md b/config/contents/rails/present.md index efd552ae..73cc031f 100644 --- a/config/contents/rails/present.md +++ b/config/contents/rails/present.md @@ -1,31 +1,40 @@ -This cops checks for code that can be changed to `blank?`. -Settings: - NotNilAndNotEmpty: Convert checks for not `nil` and `not empty?` - to `present?` - NotBlank: Convert usages of not `blank?` to `present?` - UnlessBlank: Convert usages of `unless` `blank?` to `if` `present?` - -### Example: - # NotNilAndNotEmpty: true - # bad - !foo.nil? && !foo.empty? - foo != nil && !foo.empty? - !foo.blank? - - # good - foo.present? - - # NotBlank: true - # bad - !foo.blank? - not foo.blank? - - # good - foo.present? - - # UnlessBlank: true - # bad - something unless foo.blank? - - # good - something if foo.present? \ No newline at end of file +This cop checks for code that can be written with simpler conditionals +using `Object#present?` defined by Active Support. + +Interaction with `Style/UnlessElse`: +The configuration of `NotBlank` will not produce an offense in the +context of `unless else` if `Style/UnlessElse` is inabled. This is +to prevent interference between the auto-correction of the two cops. + +### Example: NotNilAndNotEmpty: true (default) + # Converts usages of `!nil? && !empty?` to `present?` + + # bad + !foo.nil? && !foo.empty? + + # bad + foo != nil && !foo.empty? + + # good + foo.present? + +### Example: NotBlank: true (default) + # Converts usages of `!blank?` to `present?` + + # bad + !foo.blank? + + # bad + not foo.blank? + + # good + foo.present? + +### Example: UnlessBlank: true (default) + # Converts usages of `unless blank?` to `if present?` + + # bad + something unless foo.blank? + + # good + something if foo.present? \ No newline at end of file diff --git a/config/contents/rails/read_write_attribute.md b/config/contents/rails/read_write_attribute.md index bd13c372..b4fb15c7 100644 --- a/config/contents/rails/read_write_attribute.md +++ b/config/contents/rails/read_write_attribute.md @@ -1,5 +1,13 @@ -This cop checks for the use of the read_attribute or -write_attribute methods. +This cop checks for the use of the `read_attribute` or `write_attribute` +methods and recommends square brackets instead. + +If an attribute is missing from the instance (for example, when +initialized by a partial `select`) then `read_attribute` +will return nil, but square brackets will raise +an `ActiveModel::MissingAttributeError`. + +Explicitly raising an error in this situation is preferable, and that +is why rubocop recommends using square brackets. ### Example: diff --git a/config/contents/rails/redundant_allow_nil.md b/config/contents/rails/redundant_allow_nil.md new file mode 100644 index 00000000..1d688363 --- /dev/null +++ b/config/contents/rails/redundant_allow_nil.md @@ -0,0 +1,22 @@ +Checks Rails model validations for a redundant `allow_nil` when +`allow_blank` is present. + +### Example: + # bad + validates :x, length: { is: 5 }, allow_nil: true, allow_blank: true + + # bad + validates :x, length: { is: 5 }, allow_nil: false, allow_blank: true + + # bad + validates :x, length: { is: 5 }, allow_nil: false, allow_blank: false + + # good + validates :x, length: { is: 5 }, allow_blank: true + + # good + validates :x, length: { is: 5 }, allow_blank: false + + # good + # Here, `nil` is valid but `''` is not + validates :x, length: { is: 5 }, allow_nil: true, allow_blank: false diff --git a/config/contents/rails/reflection_class_name.md b/config/contents/rails/reflection_class_name.md new file mode 100644 index 00000000..d9d091c5 --- /dev/null +++ b/config/contents/rails/reflection_class_name.md @@ -0,0 +1,10 @@ +This cop checks if the value of the option `class_name`, in +the definition of a reflection is a string. + +### Example: + # bad + has_many :accounts, class_name: Account + has_many :accounts, class_name: Account.name + + # good + has_many :accounts, class_name: 'Account' \ No newline at end of file diff --git a/config/contents/rails/refute_methods.md b/config/contents/rails/refute_methods.md new file mode 100644 index 00000000..68dd79a8 --- /dev/null +++ b/config/contents/rails/refute_methods.md @@ -0,0 +1,13 @@ + +Use `assert_not` methods instead of `refute` methods. + +### Example: + # bad + refute false + refute_empty [1, 2, 3] + refute_equal true, false + + # good + assert_not false + assert_not_empty [1, 2, 3] + assert_not_equal true, false diff --git a/config/contents/rails/reversible_migration.md b/config/contents/rails/reversible_migration.md index 37f97475..3c35ba96 100644 --- a/config/contents/rails/reversible_migration.md +++ b/config/contents/rails/reversible_migration.md @@ -119,4 +119,4 @@ reversible. end end -@see http://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html \ No newline at end of file +@see https://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html \ No newline at end of file diff --git a/config/contents/rails/save_bang.md b/config/contents/rails/save_bang.md index aaf533f5..623bd0eb 100644 --- a/config/contents/rails/save_bang.md +++ b/config/contents/rails/save_bang.md @@ -2,12 +2,21 @@ This cop identifies possible cases where Active Record save! or related should be used instead of save because the model might have failed to save and an exception is better than unhandled failure. -This will ignore calls that return a boolean for success if the result -is assigned to a variable or used as the condition in an if/unless -statement. It will also ignore calls that return a model assigned to a -variable that has a call to `persisted?`. Finally, it will ignore any -call with more than 2 arguments as that is likely not an Active Record -call or a Model.update(id, attributes) call. +This will allow: +- update or save calls, assigned to a variable, + or used as a condition in an if/unless/case statement. +- create calls, assigned to a variable that then has a + call to `persisted?`. +- calls if the result is explicitly returned from methods and blocks, + or provided as arguments. +- calls whose signature doesn't look like an ActiveRecord + persistence method. + +By default it will also allow implicit returns from methods and blocks. +that behavior can be turned off with `AllowImplicitReturn: false`. + +You can permit receivers that are giving false positives with +`AllowedReceivers: []` ### Example: @@ -29,4 +38,55 @@ call or a Model.update(id, attributes) call. user = User.find_or_create_by(name: 'Joe') unless user.persisted? # ... - end \ No newline at end of file + end + + def save_user + return user.save + end + +### Example: AllowImplicitReturn: true (default) + + # good + users.each { |u| u.save } + + def save_user + user.save + end + +### Example: AllowImplicitReturn: false + + # bad + users.each { |u| u.save } + def save_user + user.save + end + + # good + users.each { |u| u.save! } + + def save_user + user.save! + end + + def save_user + return user.save + end + +### Example: AllowedReceivers: ['merchant.customers', 'Service::Mailer'] + + # bad + merchant.create + customers.builder.save + Mailer.create + + module Service::Mailer + self.create + end + + # good + merchant.customers.create + MerchantService.merchant.customers.destroy + Service::Mailer.update(message: 'Message') + ::Service::Mailer.update + Services::Service::Mailer.update(message: 'Message') + Service::Mailer::update diff --git a/config/contents/rails/skips_model_validations.md b/config/contents/rails/skips_model_validations.md index 88c62222..af12ceb7 100644 --- a/config/contents/rails/skips_model_validations.md +++ b/config/contents/rails/skips_model_validations.md @@ -1,6 +1,8 @@ This cop checks for the use of methods which skip validations which are listed in -http://guides.rubyonrails.org/active_record_validations.html#skipping-validations +https://guides.rubyonrails.org/active_record_validations.html#skipping-validations + +Methods may be ignored from this rule by configuring a `Whitelist`. ### Example: # bad @@ -11,10 +13,19 @@ http://guides.rubyonrails.org/active_record_validations.html#skipping-validation person.toggle :active product.touch Billing.update_all("category = 'authorized', author = 'David'") - user.update_attribute(website: 'example.com') + user.update_attribute(:website, 'example.com') user.update_columns(last_request_at: Time.current) Post.update_counters 5, comment_count: -1, action_count: 1 # good - user.update_attributes(website: 'example.com') - FileUtils.touch('file') \ No newline at end of file + user.update(website: 'example.com') + FileUtils.touch('file') + +### Example: Whitelist: ["touch"] + # bad + DiscussionBoard.decrement_counter(:post_count, 5) + DiscussionBoard.increment_counter(:post_count, 5) + person.toggle :active + + # good + user.touch diff --git a/config/contents/rails/time_zone.md b/config/contents/rails/time_zone.md index 1e60c2c3..7d899798 100644 --- a/config/contents/rails/time_zone.md +++ b/config/contents/rails/time_zone.md @@ -1,6 +1,6 @@ This cop checks for the use of Time methods without zone. -Built on top of Ruby on Rails style guide (https://github.com/bbatsov/rails-style-guide#time) +Built on top of Ruby on Rails style guide (https://github.com/rubocop-hq/rails-style-guide#time) and the article http://danilenko.org/2012/7/6/rails_timezones/ . Two styles are supported for this cop. When EnforcedStyle is 'strict' @@ -9,16 +9,32 @@ then only use of Time.zone is allowed. When EnforcedStyle is 'flexible' then it's also allowed to use Time.in_time_zone. -### Example: - # always offense +### Example: EnforcedStyle: strict + # `strict` means that `Time` should be used with `zone`. + + # bad + Time.now + Time.parse('2015-03-02 19:05:37') + + # bad + Time.current + Time.at(timestamp).in_time_zone + + # good + Time.zone.now + Time.zone.parse('2015-03-02 19:05:37') + +### Example: EnforcedStyle: flexible (default) + # `flexible` allows usage of `in_time_zone` instead of `zone`. + + # bad Time.now Time.parse('2015-03-02 19:05:37') - # no offense + # good Time.zone.now Time.zone.parse('2015-03-02 19:05:37') - # no offense only if style is 'flexible' + # good Time.current - DateTime.strptime(str, "%Y-%m-%d %H:%M %Z").in_time_zone Time.at(timestamp).in_time_zone \ No newline at end of file diff --git a/config/contents/rails/uniq_before_pluck.md b/config/contents/rails/uniq_before_pluck.md index 403b3f16..5116d63a 100644 --- a/config/contents/rails/uniq_before_pluck.md +++ b/config/contents/rails/uniq_before_pluck.md @@ -3,13 +3,6 @@ Prefer the use of uniq (or distinct), before pluck instead of after. The use of uniq before pluck is preferred because it executes within the database. -### Example: - # bad - Model.pluck(:id).uniq - - # good - Model.uniq.pluck(:id) - This cop has two different enforcement modes. When the EnforcedStyle is conservative (the default) then only calls to pluck on a constant (i.e. a model class) before uniq are added as offenses. @@ -19,12 +12,27 @@ uniq are added as offenses. This may lead to false positives as the cop cannot distinguish between calls to pluck on an ActiveRecord::Relation vs a call to pluck on an ActiveRecord::Associations::CollectionProxy. -### Example: +Autocorrect is disabled by default for this cop since it may generate +false positives. + +### Example: EnforcedStyle: conservative (default) + # bad + Model.pluck(:id).uniq + + # good + Model.uniq.pluck(:id) + +### Example: EnforcedStyle: aggressive + # bad # this will return a Relation that pluck is called on Model.where(cond: true).pluck(:id).uniq + # bad # an association on an instance will return a CollectionProxy instance.assoc.pluck(:id).uniq -Autocorrect is disabled by default for this cop since it may generate -false positives. + # bad + Model.pluck(:id).uniq + + # good + Model.uniq.pluck(:id) diff --git a/config/contents/rails/validation.md b/config/contents/rails/validation.md new file mode 100644 index 00000000..0f84e47c --- /dev/null +++ b/config/contents/rails/validation.md @@ -0,0 +1,28 @@ +This cop checks for the use of old-style attribute validation macros. + +### Example: + # bad + validates_acceptance_of :foo + validates_confirmation_of :foo + validates_exclusion_of :foo + validates_format_of :foo + validates_inclusion_of :foo + validates_length_of :foo + validates_numericality_of :foo + validates_presence_of :foo + validates_absence_of :foo + validates_size_of :foo + validates_uniqueness_of :foo + + # good + validates :foo, acceptance: true + validates :foo, confirmation: true + validates :foo, exclusion: true + validates :foo, format: true + validates :foo, inclusion: true + validates :foo, length: true + validates :foo, numericality: true + validates :foo, presence: true + validates :foo, absence: true + validates :foo, size: true + validates :foo, uniqueness: true diff --git a/config/contents/security/json_load.md b/config/contents/security/json_load.md index 357a0ebc..a6cb8904 100644 --- a/config/contents/security/json_load.md +++ b/config/contents/security/json_load.md @@ -10,9 +10,9 @@ option, like `JSON.parse('false', quirks_mode: true)`. Other similar issues may apply. ### Example: - # always offense + # bad JSON.load("{}") JSON.restore("{}") - # no offense + # good JSON.parse("{}") diff --git a/config/contents/security/open.md b/config/contents/security/open.md new file mode 100644 index 00000000..3a207364 --- /dev/null +++ b/config/contents/security/open.md @@ -0,0 +1,16 @@ +This cop checks for the use of `Kernel#open`. + +`Kernel#open` enables not only file access but also process invocation +by prefixing a pipe symbol (e.g., `open("| ls")`). So, it may lead to +a serious security risk by using variable input to the argument of +`Kernel#open`. It would be better to use `File.open`, `IO.popen` or +`URI#open` explicitly. + +### Example: + # bad + open(something) + + # good + File.open(something) + IO.popen(something) + URI.parse(something).open \ No newline at end of file diff --git a/config/contents/style/access_modifier_declarations.md b/config/contents/style/access_modifier_declarations.md new file mode 100644 index 00000000..8f09f172 --- /dev/null +++ b/config/contents/style/access_modifier_declarations.md @@ -0,0 +1,45 @@ +Access modifiers should be declared to apply to a group of methods +or inline before each method, depending on configuration. + +### Example: EnforcedStyle: group (default) + + # bad + + class Foo + + private def bar; end + private def baz; end + + end + + # good + + class Foo + + private + + def bar; end + def baz; end + + end +### Example: EnforcedStyle: inline + + # bad + + class Foo + + private + + def bar; end + def baz; end + + end + + # good + + class Foo + + private def bar; end + private def baz; end + + end \ No newline at end of file diff --git a/config/contents/style/and_or.md b/config/contents/style/and_or.md index 5fe53dfd..17f0e99c 100644 --- a/config/contents/style/and_or.md +++ b/config/contents/style/and_or.md @@ -1,5 +1,5 @@ This cop checks for uses of `and` and `or`, and suggests using `&&` and -`|| instead`. It can be configured to check only in conditions, or in +`||` instead. It can be configured to check only in conditions or in all contexts. ### Example: EnforcedStyle: always (default) diff --git a/config/contents/style/array_join.md b/config/contents/style/array_join.md index 43f4f5b5..44e71aab 100644 --- a/config/contents/style/array_join.md +++ b/config/contents/style/array_join.md @@ -10,4 +10,4 @@ array literal or the second is a string literal. %w(foo bar baz) * "," # good - %w(foo bar bax).join(",") + %w(foo bar baz).join(",") diff --git a/config/contents/style/begin_block.md b/config/contents/style/begin_block.md new file mode 100644 index 00000000..e37a9b77 --- /dev/null +++ b/config/contents/style/begin_block.md @@ -0,0 +1,6 @@ + +This cop checks for BEGIN blocks. + +### Example: + # bad + BEGIN { test } diff --git a/config/contents/style/block_delimiters.md b/config/contents/style/block_delimiters.md index ea82f350..27a4fd58 100644 --- a/config/contents/style/block_delimiters.md +++ b/config/contents/style/block_delimiters.md @@ -55,6 +55,30 @@ multi-line blocks. x }.inspect + # The AllowBracesOnProceduralOneLiners option is ignored unless the + # EnforcedStyle is set to `semantic`. If so: + + # If the AllowBracesOnProceduralOneLiners option is unspecified, or + # set to `false` or any other falsey value, then semantic purity is + # maintained, so one-line procedural blocks must use do-end, not + # braces. + + # bad + collection.each { |element| puts element } + + # good + collection.each do |element| puts element end + + # If the AllowBracesOnProceduralOneLiners option is set to `true`, or + # any other truthy value, then one-line procedural blocks may use + # either style. (There is no setting for requiring braces on them.) + + # good + collection.each { |element| puts element } + + # also good + collection.each do |element| puts element end + ### Example: EnforcedStyle: braces_for_chaining # bad words.each do |word| @@ -65,3 +89,14 @@ multi-line blocks. words.each { |word| word.flip.flop }.join("-") + +### Example: EnforcedStyle: always_braces + # bad + words.each do |word| + word.flip.flop + end + + # good + words.each { |word| + word.flip.flop + } diff --git a/config/contents/style/class_vars.md b/config/contents/style/class_vars.md index 677514d3..9af725fd 100644 --- a/config/contents/style/class_vars.md +++ b/config/contents/style/class_vars.md @@ -1,3 +1,26 @@ This cop checks for uses of class variables. Offenses are signaled only on assignment to class variables to -reduce the number of offenses that would be reported. \ No newline at end of file +reduce the number of offenses that would be reported. + +You have to be careful when setting a value for a class +variable; if a class has been inherited, changing the +value of a class variable also affects the inheriting +classes. This means that it's almost always better to +use a class instance variable instead. + +### Example: + # bad + class A + @@test = 10 + end + + # good + class A + @test = 10 + end + + class A + def test + @@test # you can access class variable without offense + end + end diff --git a/config/contents/style/collection_methods.md b/config/contents/style/collection_methods.md index c086a72a..011c8a80 100644 --- a/config/contents/style/collection_methods.md +++ b/config/contents/style/collection_methods.md @@ -3,4 +3,29 @@ from the Enumerable module. Unfortunately we cannot actually know if a method is from Enumerable or not (static analysis limitation), so this cop -can yield some false positives. \ No newline at end of file +can yield some false positives. + +You can customize the mapping from undesired method to desired method. + +e.g. to use `detect` over `find`: + + Style/CollectionMethods: + PreferredMethods: + find: detect + +The default mapping for `PreferredMethods` behaves as follows. + +### Example: + # bad + items.collect + items.collect! + items.inject + items.detect + items.find_all + + # good + items.map + items.map! + items.reduce + items.find + items.select diff --git a/config/contents/style/commented_keyword.md b/config/contents/style/commented_keyword.md index cafebf5e..cb0db33d 100644 --- a/config/contents/style/commented_keyword.md +++ b/config/contents/style/commented_keyword.md @@ -1,8 +1,8 @@ This cop checks for comments put on the same line as some keywords. These keywords are: `begin`, `class`, `def`, `end`, `module`. -Note that some comments (such as `:nodoc:` and `rubocop:disable`) are -allowed. +Note that some comments (`:nodoc:`, `:yields:, and `rubocop:disable`) +are allowed. ### Example: # bad diff --git a/config/contents/style/constant_visibility.md b/config/contents/style/constant_visibility.md new file mode 100644 index 00000000..60c50530 --- /dev/null +++ b/config/contents/style/constant_visibility.md @@ -0,0 +1,22 @@ +This cop checks that constants defined in classes and modules have +an explicit visibility declaration. By default, Ruby makes all class- +and module constants public, which litters the public API of the +class or module. Explicitly declaring a visibility makes intent more +clear, and prevents outside actors from touching private state. + +### Example: + + # bad + class Foo + BAR = 42 + BAZ = 43 + end + + # good + class Foo + BAR = 42 + private_constant :BAR + + BAZ = 43 + public_constant :BAZ + end diff --git a/config/contents/style/copyright.md b/config/contents/style/copyright.md index 39d59b74..4e507770 100644 --- a/config/contents/style/copyright.md +++ b/config/contents/style/copyright.md @@ -1,11 +1,11 @@ Check that a copyright notice was given in each source file. The default regexp for an acceptable copyright notice can be found in -config/default.yml. The default can be changed as follows: +config/default.yml. The default can be changed as follows: Style/Copyright: Notice: '^Copyright (\(c\) )?2\d{3} Acme Inc' -This regex string is treated as an unanchored regex. For each file +This regex string is treated as an unanchored regex. For each file that RuboCop scans, a comment that matches this regex must be found or an offense is reported. diff --git a/config/contents/style/date_time.md b/config/contents/style/date_time.md index 0ce72d97..6c16e202 100644 --- a/config/contents/style/date_time.md +++ b/config/contents/style/date_time.md @@ -1,5 +1,8 @@ -This cop checks for uses of `DateTime` that should be replaced by -`Date` or `Time`. +This cop checks for consistent usage of the `DateTime` class over the +`Time` class. This cop is disabled by default since these classes, +although highly overlapping, have particularities that make them not +replaceable in certain situations when dealing with multiple timezones +and/or DST. ### Example: @@ -12,8 +15,24 @@ This cop checks for uses of `DateTime` that should be replaced by # bad - uses `DateTime` for modern date DateTime.iso8601('2016-06-29') - # good - uses `Date` for modern date - Date.iso8601('2016-06-29') + # good - uses `Time` for modern date + Time.iso8601('2016-06-29') # good - uses `DateTime` with start argument for historical date - DateTime.iso8601('1751-04-23', Date::ENGLAND) \ No newline at end of file + DateTime.iso8601('1751-04-23', Date::ENGLAND) + +### Example: AllowCoercion: false (default) + + # bad - coerces to `DateTime` + something.to_datetime + + # good - coerces to `Time` + something.to_time + +### Example: AllowCoercion: true + + # good + something.to_datetime + + # good + something.to_time \ No newline at end of file diff --git a/config/contents/style/empty_literal.md b/config/contents/style/empty_literal.md index 6f2006f9..64ccfaaf 100644 --- a/config/contents/style/empty_literal.md +++ b/config/contents/style/empty_literal.md @@ -1,5 +1,5 @@ This cop checks for the use of a method, the result of which -would be a literal, like an empty array, hash or string. +would be a literal, like an empty array, hash, or string. ### Example: # bad diff --git a/config/contents/style/encoding.md b/config/contents/style/encoding.md new file mode 100644 index 00000000..c85a0b99 --- /dev/null +++ b/config/contents/style/encoding.md @@ -0,0 +1,6 @@ +This cop checks ensures source files have no utf-8 encoding comments. +### Example: + # bad + # encoding: UTF-8 + # coding: UTF-8 + # -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/config/contents/style/end_block.md b/config/contents/style/end_block.md new file mode 100644 index 00000000..8f05ddfe --- /dev/null +++ b/config/contents/style/end_block.md @@ -0,0 +1,8 @@ +This cop checks for END blocks. + +### Example: + # bad + END { puts 'Goodbye!' } + + # good + at_exit { puts 'Goodbye!' } diff --git a/config/contents/style/even_odd.md b/config/contents/style/even_odd.md index 83ed6897..c79711b9 100644 --- a/config/contents/style/even_odd.md +++ b/config/contents/style/even_odd.md @@ -1,5 +1,5 @@ -This cop checks for places where Integer#even? or Integer#odd? -should have been used. +This cop checks for places where `Integer#even?` or `Integer#odd?` +can be used. ### Example: diff --git a/config/contents/style/expand_path_arguments.md b/config/contents/style/expand_path_arguments.md new file mode 100644 index 00000000..baea3e0b --- /dev/null +++ b/config/contents/style/expand_path_arguments.md @@ -0,0 +1,36 @@ +This cop checks for use of the `File.expand_path` arguments. +Likewise, it also checks for the `Pathname.new` argument. + +Contrastive bad case and good case are alternately shown in +the following examples. + +### Example: + # bad + File.expand_path('..', __FILE__) + + # good + File.expand_path(__dir__) + + # bad + File.expand_path('../..', __FILE__) + + # good + File.expand_path('..', __dir__) + + # bad + File.expand_path('.', __FILE__) + + # good + File.expand_path(__FILE__) + + # bad + Pathname(__FILE__).parent.expand_path + + # good + Pathname(__dir__).expand_path + + # bad + Pathname.new(__FILE__).parent.expand_path + + # good + Pathname.new(__dir__).expand_path diff --git a/config/contents/style/for.md b/config/contents/style/for.md index 70f68e5f..96edb4cb 100644 --- a/config/contents/style/for.md +++ b/config/contents/style/for.md @@ -1,4 +1,34 @@ -This cop looks for uses of the *for* keyword, or *each* method. The +This cop looks for uses of the `for` keyword or `each` method. The preferred alternative is set in the EnforcedStyle configuration -parameter. An *each* call with a block on a single line is always -allowed, however. \ No newline at end of file +parameter. An `each` call with a block on a single line is always +allowed. + +### Example: EnforcedStyle: each (default) + # bad + def foo + for n in [1, 2, 3] do + puts n + end + end + + # good + def foo + [1, 2, 3].each do |n| + puts n + end + end + +### Example: EnforcedStyle: for + # bad + def foo + [1, 2, 3].each do |n| + puts n + end + end + + # good + def foo + for n in [1, 2, 3] do + puts n + end + end diff --git a/config/contents/style/format_string.md b/config/contents/style/format_string.md index c3720ff0..9dce92ce 100644 --- a/config/contents/style/format_string.md +++ b/config/contents/style/format_string.md @@ -6,7 +6,7 @@ manner for all cases, so only two scenarios are considered - if the first argument is a string literal and if the second argument is an array literal. -### Example: EnforcedStyle: format(default) +### Example: EnforcedStyle: format (default) # bad puts sprintf('%10s', 'hoge') puts '%10s' % 'hoge' diff --git a/config/contents/style/frozen_string_literal_comment.md b/config/contents/style/frozen_string_literal_comment.md index 43bf7513..a6835482 100644 --- a/config/contents/style/frozen_string_literal_comment.md +++ b/config/contents/style/frozen_string_literal_comment.md @@ -1,7 +1,7 @@ -This cop is designed to help upgrade to Ruby 3.0. It will add the +This cop is designed to help upgrade to after Ruby 3.0. It will add the comment `# frozen_string_literal: true` to the top of files to enable frozen string literals. Frozen string literals may be default -in Ruby 3.0. The comment will be added below a shebang and encoding +after Ruby 3.0. The comment will be added below a shebang and encoding comment. The frozen string literal comment is only valid in Ruby 2.3+. ### Example: EnforcedStyle: when_needed (default) diff --git a/config/contents/style/global_vars.md b/config/contents/style/global_vars.md index 3e388b84..73832516 100644 --- a/config/contents/style/global_vars.md +++ b/config/contents/style/global_vars.md @@ -1,4 +1,4 @@ -This cops looks for uses of global variables. +This cop looks for uses of global variables. It does not report offenses for built-in global variables. Built-in global variables are allowed by default. Additionally users can allow additional variables via the AllowedVariables option. diff --git a/config/contents/style/if_unless_modifier.md b/config/contents/style/if_unless_modifier.md index ed38881d..19b54b6d 100644 --- a/config/contents/style/if_unless_modifier.md +++ b/config/contents/style/if_unless_modifier.md @@ -1,6 +1,7 @@ Checks for if and unless statements that would fit on one line if written as a modifier if/unless. The maximum line length is -configured in the `Metrics/LineLength` cop. +configured in the `Metrics/LineLength` cop. The tab size is configured +in the `IndentationWidth` of the `Layout/Tab` cop. ### Example: # bad diff --git a/config/contents/style/inverse_methods.md b/config/contents/style/inverse_methods.md index db8fa0bc..b87fc812 100644 --- a/config/contents/style/inverse_methods.md +++ b/config/contents/style/inverse_methods.md @@ -21,4 +21,5 @@ of the block that is passed to the method should be defined in foo.any? { |f| f.even? } foo != bar foo == bar - !!('foo' =~ /^\w+$/) \ No newline at end of file + !!('foo' =~ /^\w+$/) + !(foo.class < Numeric) # Checking class hierarchy is allowed \ No newline at end of file diff --git a/config/contents/style/ip_addresses.md b/config/contents/style/ip_addresses.md new file mode 100644 index 00000000..721fddb2 --- /dev/null +++ b/config/contents/style/ip_addresses.md @@ -0,0 +1,13 @@ +This cop checks for hardcoded IP addresses, which can make code +brittle. IP addresses are likely to need to be changed when code +is deployed to a different server or environment, which may break +a deployment if forgotten. Prefer setting IP addresses in ENV or +other configuration. + +### Example: + + # bad + ip_address = '127.59.241.29' + + # good + ip_address = ENV['DEPLOYMENT_IP_ADDRESS'] \ No newline at end of file diff --git a/config/contents/style/method_call_with_args_parentheses.md b/config/contents/style/method_call_with_args_parentheses.md deleted file mode 100644 index c156ac6f..00000000 --- a/config/contents/style/method_call_with_args_parentheses.md +++ /dev/null @@ -1,36 +0,0 @@ -This cop checks presence of parentheses in method calls containing -parameters. By default, macro methods are ignored. Additional methods -can be added to the `IgnoredMethods` list. - -### Example: - - # bad - array.delete e - - # good - array.delete(e) - - # good - # Operators don't need parens - foo == bar - - # good - # Setter methods don't need parens - foo.bar = baz - - # okay with `puts` listed in `IgnoredMethods` - puts 'test' - - # IgnoreMacros: true (default) - - # good - class Foo - bar :baz - end - - # IgnoreMacros: false - - # bad - class Foo - bar :baz - end \ No newline at end of file diff --git a/config/contents/style/method_def_parentheses.md b/config/contents/style/method_def_parentheses.md index 28f34928..b09b7c8a 100644 --- a/config/contents/style/method_def_parentheses.md +++ b/config/contents/style/method_def_parentheses.md @@ -1,4 +1,4 @@ -This cops checks for parentheses around the arguments in method +This cop checks for parentheses around the arguments in method definitions. Both instance and class/singleton methods are checked. ### Example: EnforcedStyle: require_parentheses (default) @@ -55,8 +55,8 @@ definitions. Both instance and class/singleton methods are checked. ### Example: EnforcedStyle: require_no_parentheses_except_multiline # The `require_no_parentheses_except_multiline` style prefers no - # parantheses when method definition arguments fit on single line, - # but prefers parantheses when arguments span multiple lines. + # parentheses when method definition arguments fit on single line, + # but prefers parentheses when arguments span multiple lines. # bad def bar(num1, num2) diff --git a/config/contents/style/method_missing_super.md b/config/contents/style/method_missing_super.md new file mode 100644 index 00000000..4117e35d --- /dev/null +++ b/config/contents/style/method_missing_super.md @@ -0,0 +1,15 @@ +This cop checks for the presence of `method_missing` without +falling back on `super`. + +### Example: + #bad + def method_missing(name, *args) + # ... + end + + #good + + def method_missing(name, *args) + # ... + super + end \ No newline at end of file diff --git a/config/contents/style/missing_else.md b/config/contents/style/missing_else.md index addee86b..eed12751 100644 --- a/config/contents/style/missing_else.md +++ b/config/contents/style/missing_else.md @@ -1,25 +1,90 @@ Checks for `if` expressions that do not have an `else` branch. -SupportedStyles -if -### Example: +Supported styles are: if, case, both. + +### Example: EnforcedStyle: if + # warn when an `if` expression is missing an `else` branch. + # bad if condition statement end -case -### Example: + # good + if condition + statement + else + # the content of `else` branch will be determined by Style/EmptyElse + end + + # good + case var + when condition + statement + end + + # good + case var + when condition + statement + else + # the content of `else` branch will be determined by Style/EmptyElse + end + +### Example: EnforcedStyle: case + # warn when a `case` expression is missing an `else` branch. + # bad case var when condition statement end -### Example: + # good + case var + when condition + statement + else + # the content of `else` branch will be determined by Style/EmptyElse + end + # good if condition statement + end + + # good + if condition + statement + else + # the content of `else` branch will be determined by Style/EmptyElse + end + +### Example: EnforcedStyle: both (default) + # warn when an `if` or `case` expression is missing an `else` branch. + + # bad + if condition + statement + end + + # bad + case var + when condition + statement + end + + # good + if condition + statement + else + # the content of `else` branch will be determined by Style/EmptyElse + end + + # good + case var + when condition + statement else - # the content of the else branch will be determined by Style/EmptyElse + # the content of `else` branch will be determined by Style/EmptyElse end \ No newline at end of file diff --git a/config/contents/style/missing_respond_to_missing.md b/config/contents/style/missing_respond_to_missing.md new file mode 100644 index 00000000..4c6a83fa --- /dev/null +++ b/config/contents/style/missing_respond_to_missing.md @@ -0,0 +1,17 @@ +This cop checks for the presence of `method_missing` without also +defining `respond_to_missing?`. + +### Example: + #bad + def method_missing(name, *args) + # ... + end + + #good + def respond_to_missing?(name, include_private) + # ... + end + + def method_missing(name, *args) + # ... + end diff --git a/config/contents/style/mixin_usage.md b/config/contents/style/mixin_usage.md index 06c9d126..dc106427 100644 --- a/config/contents/style/mixin_usage.md +++ b/config/contents/style/mixin_usage.md @@ -1,8 +1,6 @@ -This cop checks that `include`, `extend` and `prepend` exists at -the top level. -Using these at the top level affects the behavior of `Object`. -There will not be using `include`, `extend` and `prepend` at -the top level. Let's use it inside `class` or `module`. +This cop checks that `include`, `extend` and `prepend` statements appear +inside classes and modules, not at the top level, so as to not affect +the behavior of `Object`. ### Example: # bad diff --git a/config/contents/style/module_function.md b/config/contents/style/module_function.md index dc05a05c..b7a593ad 100644 --- a/config/contents/style/module_function.md +++ b/config/contents/style/module_function.md @@ -1,4 +1,4 @@ -This cops checks for use of `extend self` or `module_function` in a +This cop checks for use of `extend self` or `module_function` in a module. Supported styles are: module_function, extend_self. @@ -16,6 +16,18 @@ Supported styles are: module_function, extend_self. # ... end +In case there are private methods, the cop won't be activated. +Otherwise, it forces to change the flow of the default code. + +### Example: EnforcedStyle: module_function (default) + # good + module Test + extend self + # ... + private + # ... + end + ### Example: EnforcedStyle: extend_self # bad module Test @@ -29,5 +41,5 @@ Supported styles are: module_function, extend_self. # ... end -These offenses are not auto-corrected since there are different +These offenses are not safe to auto-correct since there are different implications to each approach. \ No newline at end of file diff --git a/config/contents/style/multiline_method_signature.md b/config/contents/style/multiline_method_signature.md new file mode 100644 index 00000000..3ed7ccfc --- /dev/null +++ b/config/contents/style/multiline_method_signature.md @@ -0,0 +1,14 @@ +This cop checks for method signatures that span multiple lines. + +### Example: + + # good + + def foo(bar, baz) + end + + # bad + + def foo(bar, + baz) + end diff --git a/config/contents/style/mutable_constant.md b/config/contents/style/mutable_constant.md index 074bc292..4a8e7411 100644 --- a/config/contents/style/mutable_constant.md +++ b/config/contents/style/mutable_constant.md @@ -1,9 +1,47 @@ This cop checks whether some constant value isn't a mutable literal (e.g. array or hash). -### Example: +Strict mode can be used to freeze all constants, rather than +just literals. +Strict mode is considered an experimental feature. It has not been +updated with an exhaustive list of all methods that will produce +frozen objects so there is a decent chance of getting some false +positives. Luckily, there is no harm in freezing an already +frozen object. + +### Example: EnforcedStyle: literals (default) # bad CONST = [1, 2, 3] # good - CONST = [1, 2, 3].freeze \ No newline at end of file + CONST = [1, 2, 3].freeze + + # good + CONST = <<~TESTING.freeze + This is a heredoc + TESTING + + # good + CONST = Something.new + + +### Example: EnforcedStyle: strict + # bad + CONST = Something.new + + # bad + CONST = Struct.new do + def foo + puts 1 + end + end + + # good + CONST = Something.new.freeze + + # good + CONST = Struct.new do + def foo + puts 1 + end + end.freeze \ No newline at end of file diff --git a/config/contents/style/negated_while.md b/config/contents/style/negated_while.md new file mode 100644 index 00000000..a4e96768 --- /dev/null +++ b/config/contents/style/negated_while.md @@ -0,0 +1,19 @@ +Checks for uses of while with a negated condition. + +### Example: + # bad + while !foo + bar + end + + # good + until foo + bar + end + + # bad + bar until !foo + + # good + bar while foo + bar while !foo && baz \ No newline at end of file diff --git a/config/contents/style/nested_ternary_operator.md b/config/contents/style/nested_ternary_operator.md new file mode 100644 index 00000000..18dd12cb --- /dev/null +++ b/config/contents/style/nested_ternary_operator.md @@ -0,0 +1,12 @@ +This cop checks for nested ternary op expressions. + +### Example: + # bad + a ? (b ? b1 : b2) : a2 + + # good + if a + b ? b1 : b2 + else + a2 + end \ No newline at end of file diff --git a/config/contents/style/nil_comparison.md b/config/contents/style/nil_comparison.md index 7527dbba..1c25ffe3 100644 --- a/config/contents/style/nil_comparison.md +++ b/config/contents/style/nil_comparison.md @@ -1,6 +1,9 @@ -This cop checks for comparison of something with nil using ==. +This cop checks for comparison of something with nil using `==` and +`nil?`. -### Example: +Supported styles are: predicate, comparison. + +### Example: EnforcedStyle: predicate (default) # bad if x == nil @@ -8,4 +11,14 @@ This cop checks for comparison of something with nil using ==. # good if x.nil? - end \ No newline at end of file + end + +### Example: EnforcedStyle: comparison + + # bad + if x.nil? + end + + # good + if x == nil + end diff --git a/config/contents/style/numeric_literal_prefix.md b/config/contents/style/numeric_literal_prefix.md index 27d6a694..3834a971 100644 --- a/config/contents/style/numeric_literal_prefix.md +++ b/config/contents/style/numeric_literal_prefix.md @@ -1,7 +1,30 @@ -This cop checks for octal, hex, binary and decimal literals using +This cop checks for octal, hex, binary, and decimal literals using uppercase prefixes and corrects them to lowercase prefix or no prefix (in case of decimals). -eg. for octal use `0o` instead of `0` or `0O`. -Can be configured to use `0` only for octal literals using -`EnforcedOctalStyle` => `zero_only` \ No newline at end of file +### Example: EnforcedOctalStyle: zero_with_o (default) + # bad - missing octal prefix + num = 01234 + + # bad - uppercase prefix + num = 0O1234 + num = 0X12AB + num = 0B10101 + + # bad - redundant decimal prefix + num = 0D1234 + num = 0d1234 + + # good + num = 0o1234 + num = 0x12AB + num = 0b10101 + num = 1234 + +### Example: EnforcedOctalStyle: zero_only + # bad + num = 0o1234 + num = 0O1234 + + # good + num = 01234 \ No newline at end of file diff --git a/config/contents/style/numeric_predicate.md b/config/contents/style/numeric_predicate.md index 506c012c..5629863f 100644 --- a/config/contents/style/numeric_predicate.md +++ b/config/contents/style/numeric_predicate.md @@ -9,7 +9,7 @@ but not `true` and `false`, and thus not always interchangeable with The cop ignores comparisons to global variables, since they are often populated with objects which can be compared with integers, but are -not themselves `Interger` polymorphic. +not themselves `Integer` polymorphic. ### Example: EnforcedStyle: predicate (default) # bad diff --git a/config/contents/style/one_line_conditional.md b/config/contents/style/one_line_conditional.md new file mode 100644 index 00000000..617023f6 --- /dev/null +++ b/config/contents/style/one_line_conditional.md @@ -0,0 +1,19 @@ +TODO: Make configurable. +Checks for uses of if/then/else/end on a single line. + +### Example: + # bad + if foo then boo else doo end + unless foo then boo else goo end + + # good + foo ? boo : doo + boo if foo + if foo then boo end + + # good + if foo + boo + else + doo + end \ No newline at end of file diff --git a/config/contents/style/parentheses_around_condition.md b/config/contents/style/parentheses_around_condition.md index e8fa7e83..838fd074 100644 --- a/config/contents/style/parentheses_around_condition.md +++ b/config/contents/style/parentheses_around_condition.md @@ -16,4 +16,21 @@ condition of if/unless/while/until. if x > 10 elsif x < 3 + end + +### Example: AllowInMultilineConditions: false (default) + # bad + if (x > 10 && + y > 10) + end + + # good + if x > 10 && + y > 10 + end + +### Example: AllowInMultilineConditions: true + # good + if (x > 10 && + y > 10) end \ No newline at end of file diff --git a/config/contents/style/proc.md b/config/contents/style/proc.md index cfe47225..82300e34 100644 --- a/config/contents/style/proc.md +++ b/config/contents/style/proc.md @@ -1,4 +1,4 @@ -This cops checks for uses of Proc.new where Kernel#proc +This cop checks for uses of Proc.new where Kernel#proc would be more appropriate. ### Example: diff --git a/config/contents/style/redundant_begin.md b/config/contents/style/redundant_begin.md index 587c62bd..97a0abec 100644 --- a/config/contents/style/redundant_begin.md +++ b/config/contents/style/redundant_begin.md @@ -4,6 +4,7 @@ Currently it checks for code like this: ### Example: + # bad def redundant begin ala @@ -13,9 +14,38 @@ Currently it checks for code like this: end end + # good def preferred ala bala rescue StandardError => e something + end + + # bad + # When using Ruby 2.5 or later. + do_something do + begin + something + rescue => ex + anything + end + end + + # good + # In Ruby 2.5 or later, you can omit `begin` in `do-end` block. + do_something do + something + rescue => ex + anything + end + + # good + # Stabby lambdas don't support implicit `begin` in `do-end` blocks. + -> do + begin + foo + rescue Bar + baz + end end \ No newline at end of file diff --git a/config/contents/style/redundant_return.md b/config/contents/style/redundant_return.md index 44e0ac76..80b6cdc2 100644 --- a/config/contents/style/redundant_return.md +++ b/config/contents/style/redundant_return.md @@ -1,11 +1,15 @@ This cop checks for redundant `return` expressions. ### Example: + # These bad cases should be extended to handle methods whose body is + # if/else or a case expression with a default branch. + # bad def test return something end + # bad def test one two @@ -13,5 +17,15 @@ This cop checks for redundant `return` expressions. return something end -It should be extended to handle methods whose body is if/else -or a case expression with a default branch. \ No newline at end of file + # good + def test + return something if something_else + end + + # good + def test + if x + elsif y + else + end + end diff --git a/config/contents/style/redundant_sort_by.md b/config/contents/style/redundant_sort_by.md new file mode 100644 index 00000000..a03586dc --- /dev/null +++ b/config/contents/style/redundant_sort_by.md @@ -0,0 +1,12 @@ +This cop identifies places where `sort_by { ... }` can be replaced by +`sort`. + +### Example: + # bad + array.sort_by { |x| x } + array.sort_by do |var| + var + end + + # good + array.sort \ No newline at end of file diff --git a/config/contents/style/safe_navigation.md b/config/contents/style/safe_navigation.md index c52b6458..2e0e303d 100644 --- a/config/contents/style/safe_navigation.md +++ b/config/contents/style/safe_navigation.md @@ -1,6 +1,9 @@ This cop transforms usages of a method call safeguarded by a non `nil` check for the variable whose method is being called to -safe navigation (`&.`). +safe navigation (`&.`). If there is a method chain, all of the methods +in the chain need to be checked for safety, and all of the methods will +need to be changed to use safe navigation. We have limited the cop to +not register an offense for method chains that exceed 2 methods. Configuration option: ConvertCodeThatCanStartToReturnNil The default for this is `false`. When configured to `true`, this will @@ -13,6 +16,7 @@ returns. ### Example: # bad foo.bar if foo + foo.bar.baz if foo foo.bar(param1, param2) if foo foo.bar { |e| e.something } if foo foo.bar(param) { |e| e.something } if foo @@ -22,19 +26,30 @@ returns. foo.bar unless foo.nil? foo && foo.bar + foo && foo.bar.baz foo && foo.bar(param1, param2) foo && foo.bar { |e| e.something } foo && foo.bar(param) { |e| e.something } # good foo&.bar + foo&.bar&.baz foo&.bar(param1, param2) foo&.bar { |e| e.something } foo&.bar(param) { |e| e.something } + foo && foo.bar.baz.qux # method chain with more than 2 methods + foo && foo.nil? # method that `nil` responds to + # Method calls that do not use `.` + foo && foo < bar + foo < bar if foo + + # This could start returning `nil` as well as the return of the method foo.nil? || foo.bar !foo || foo.bar - # Methods that `nil` will `respond_to?` should not be converted to - # use safe navigation - foo.to_i if foo \ No newline at end of file + # Methods that are used on assignment, arithmetic operation or + # comparison should not be converted to use safe navigation + foo.baz = bar if foo + foo.baz + bar if foo + foo.bar > 2 if foo \ No newline at end of file diff --git a/config/contents/style/sample.md b/config/contents/style/sample.md new file mode 100644 index 00000000..104eaec2 --- /dev/null +++ b/config/contents/style/sample.md @@ -0,0 +1,24 @@ +This cop is used to identify usages of `shuffle.first`, +`shuffle.last`, and `shuffle[]` and change them to use +`sample` instead. + +### Example: + # bad + [1, 2, 3].shuffle.first + [1, 2, 3].shuffle.first(2) + [1, 2, 3].shuffle.last + [2, 1, 3].shuffle.at(0) + [2, 1, 3].shuffle.slice(0) + [1, 2, 3].shuffle[2] + [1, 2, 3].shuffle[0, 2] # sample(2) will do the same + [1, 2, 3].shuffle[0..2] # sample(3) will do the same + [1, 2, 3].shuffle(random: Random.new).first + + # good + [1, 2, 3].shuffle + [1, 2, 3].sample + [1, 2, 3].sample(3) + [1, 2, 3].shuffle[1, 3] # sample(3) might return a longer Array + [1, 2, 3].shuffle[1..3] # sample(3) might return a longer Array + [1, 2, 3].shuffle[foo, bar] + [1, 2, 3].shuffle(random: Random.new) \ No newline at end of file diff --git a/config/contents/style/single_line_block_params.md b/config/contents/style/single_line_block_params.md index 5436ec1b..8721bd0e 100644 --- a/config/contents/style/single_line_block_params.md +++ b/config/contents/style/single_line_block_params.md @@ -2,4 +2,24 @@ This cop checks whether the block parameters of a single-line method accepting a block match the names specified via configuration. For instance one can configure `reduce`(`inject`) to use |a, e| as -parameters. \ No newline at end of file +parameters. + +Configuration option: Methods +Should be set to use this cop. Array of hashes, where each key is the +method name and value - array of argument names. + +### Example: Methods: [{reduce: %w[a b]}] + # bad + foo.reduce { |c, d| c + d } + foo.reduce { |_, _d| 1 } + + # good + foo.reduce { |a, b| a + b } + foo.reduce { |a, _b| a } + foo.reduce { |a, (id, _)| a + id } + foo.reduce { true } + + # good + foo.reduce do |c, d| + c + d + end \ No newline at end of file diff --git a/config/contents/style/special_global_vars.md b/config/contents/style/special_global_vars.md new file mode 100644 index 00000000..c4679afa --- /dev/null +++ b/config/contents/style/special_global_vars.md @@ -0,0 +1,52 @@ + +This cop looks for uses of Perl-style global variables. + +### Example: EnforcedStyle: use_english_names (default) + # good + puts $LOAD_PATH + puts $LOADED_FEATURES + puts $PROGRAM_NAME + puts $ERROR_INFO + puts $ERROR_POSITION + puts $FIELD_SEPARATOR # or $FS + puts $OUTPUT_FIELD_SEPARATOR # or $OFS + puts $INPUT_RECORD_SEPARATOR # or $RS + puts $OUTPUT_RECORD_SEPARATOR # or $ORS + puts $INPUT_LINE_NUMBER # or $NR + puts $LAST_READ_LINE + puts $DEFAULT_OUTPUT + puts $DEFAULT_INPUT + puts $PROCESS_ID # or $PID + puts $CHILD_STATUS + puts $LAST_MATCH_INFO + puts $IGNORECASE + puts $ARGV # or ARGV + puts $MATCH + puts $PREMATCH + puts $POSTMATCH + puts $LAST_PAREN_MATCH + +### Example: EnforcedStyle: use_perl_names + # good + puts $: + puts $" + puts $0 + puts $! + puts $@ + puts $; + puts $, + puts $/ + puts $\ + puts $. + puts $_ + puts $> + puts $< + puts $$ + puts $? + puts $~ + puts $= + puts $* + puts $& + puts $` + puts $' + puts $+ diff --git a/config/contents/style/stderr_puts.md b/config/contents/style/stderr_puts.md index b9e39a04..5210f6da 100644 --- a/config/contents/style/stderr_puts.md +++ b/config/contents/style/stderr_puts.md @@ -1,6 +1,6 @@ This cop identifies places where `$stderr.puts` can be replaced by `warn`. The latter has the advantage of easily being disabled by, -e.g. the -W0 interpreter flag, or setting $VERBOSE to nil. +the `-W0` interpreter flag or setting `$VERBOSE` to `nil`. ### Example: # bad diff --git a/config/contents/style/strip.md b/config/contents/style/strip.md new file mode 100644 index 00000000..20f263b1 --- /dev/null +++ b/config/contents/style/strip.md @@ -0,0 +1,10 @@ +This cop identifies places where `lstrip.rstrip` can be replaced by +`strip`. + +### Example: + # bad + 'abc'.lstrip.rstrip + 'abc'.rstrip.lstrip + + # good + 'abc'.strip \ No newline at end of file diff --git a/config/contents/style/struct_inheritance.md b/config/contents/style/struct_inheritance.md index 4eb00d93..9723ff57 100644 --- a/config/contents/style/struct_inheritance.md +++ b/config/contents/style/struct_inheritance.md @@ -3,7 +3,14 @@ This cop checks for inheritance from Struct.new. ### Example: # bad class Person < Struct.new(:first_name, :last_name) + def age + 42 + end end # good - Person = Struct.new(:first_name, :last_name) \ No newline at end of file + Person = Struct.new(:first_name, :last_name) do + def age + 42 + end + end \ No newline at end of file diff --git a/config/contents/style/trailing_body_on_class.md b/config/contents/style/trailing_body_on_class.md new file mode 100644 index 00000000..4e8d0098 --- /dev/null +++ b/config/contents/style/trailing_body_on_class.md @@ -0,0 +1,11 @@ +This cop checks for trailing code after the class definition. + +### Example: + # bad + class Foo; def foo; end + end + + # good + class Foo + def foo; end + end diff --git a/config/contents/style/trailing_body_on_module.md b/config/contents/style/trailing_body_on_module.md new file mode 100644 index 00000000..3e42155f --- /dev/null +++ b/config/contents/style/trailing_body_on_module.md @@ -0,0 +1,11 @@ +This cop checks for trailing code after the module definition. + +### Example: + # bad + module Foo extend self + end + + # good + module Foo + extend self + end diff --git a/config/contents/style/trailing_comma_in_arguments.md b/config/contents/style/trailing_comma_in_arguments.md index 2a8bf88b..d02884b0 100644 --- a/config/contents/style/trailing_comma_in_arguments.md +++ b/config/contents/style/trailing_comma_in_arguments.md @@ -4,6 +4,9 @@ This cop checks for trailing comma in argument lists. # bad method(1, 2,) + # good + method(1, 2) + # good method( 1, 2, @@ -20,6 +23,9 @@ This cop checks for trailing comma in argument lists. # bad method(1, 2,) + # good + method(1, 2) + # good method( 1, @@ -30,6 +36,9 @@ This cop checks for trailing comma in argument lists. # bad method(1, 2,) + # good + method(1, 2) + # good method( 1, diff --git a/config/contents/style/trailing_comma_in_array_literal.md b/config/contents/style/trailing_comma_in_array_literal.md new file mode 100644 index 00000000..1fc7cd63 --- /dev/null +++ b/config/contents/style/trailing_comma_in_array_literal.md @@ -0,0 +1,37 @@ +This cop checks for trailing comma in array literals. + +### Example: EnforcedStyleForMultiline: consistent_comma + # bad + a = [1, 2,] + + # good + a = [ + 1, 2, + 3, + ] + + # good + a = [ + 1, + 2, + ] + +### Example: EnforcedStyleForMultiline: comma + # bad + a = [1, 2,] + + # good + a = [ + 1, + 2, + ] + +### Example: EnforcedStyleForMultiline: no_comma (default) + # bad + a = [1, 2,] + + # good + a = [ + 1, + 2 + ] \ No newline at end of file diff --git a/config/contents/style/trailing_comma_in_hash_literal.md b/config/contents/style/trailing_comma_in_hash_literal.md new file mode 100644 index 00000000..1988c66b --- /dev/null +++ b/config/contents/style/trailing_comma_in_hash_literal.md @@ -0,0 +1,37 @@ +This cop checks for trailing comma in hash literals. + +### Example: EnforcedStyleForMultiline: consistent_comma + # bad + a = { foo: 1, bar: 2, } + + # good + a = { + foo: 1, bar: 2, + qux: 3, + } + + # good + a = { + foo: 1, + bar: 2, + } + +### Example: EnforcedStyleForMultiline: comma + # bad + a = { foo: 1, bar: 2, } + + # good + a = { + foo: 1, + bar: 2, + } + +### Example: EnforcedStyleForMultiline: no_comma (default) + # bad + a = { foo: 1, bar: 2, } + + # good + a = { + foo: 1, + bar: 2 + } \ No newline at end of file diff --git a/config/contents/style/unneeded_condition.md b/config/contents/style/unneeded_condition.md new file mode 100644 index 00000000..ad752bfa --- /dev/null +++ b/config/contents/style/unneeded_condition.md @@ -0,0 +1,26 @@ +This cop checks for unnecessary conditional expressions. + +### Example: + # bad + a = b ? b : c + + # good + a = b || c + +### Example: + # bad + if b + b + else + c + end + + # good + b || c + + # good + if b + b + elsif cond + c + end diff --git a/config/contents/style/unneeded_percent_q.md b/config/contents/style/unneeded_percent_q.md new file mode 100644 index 00000000..ff90e3dd --- /dev/null +++ b/config/contents/style/unneeded_percent_q.md @@ -0,0 +1,13 @@ +This cop checks for usage of the %q/%Q syntax when '' or "" would do. + +### Example: + + # bad + name = %q(Bruce Wayne) + time = %q(8 o'clock) + question = %q("What did you say?") + + # good + name = 'Bruce Wayne' + time = "8 o'clock" + question = '"What did you say?"' diff --git a/config/contents/style/unneeded_sort.md b/config/contents/style/unneeded_sort.md new file mode 100644 index 00000000..06dc33b1 --- /dev/null +++ b/config/contents/style/unneeded_sort.md @@ -0,0 +1,45 @@ +This cop is used to identify instances of sorting and then +taking only the first or last element. The same behavior can +be accomplished without a relatively expensive sort by using +`Enumerable#min` instead of sorting and taking the first +element and `Enumerable#max` instead of sorting and taking the +last element. Similarly, `Enumerable#min_by` and +`Enumerable#max_by` can replace `Enumerable#sort_by` calls +after which only the first or last element is used. + +### Example: + # bad + [2, 1, 3].sort.first + [2, 1, 3].sort[0] + [2, 1, 3].sort.at(0) + [2, 1, 3].sort.slice(0) + + # good + [2, 1, 3].min + + # bad + [2, 1, 3].sort.last + [2, 1, 3].sort[-1] + [2, 1, 3].sort.at(-1) + [2, 1, 3].sort.slice(-1) + + # good + [2, 1, 3].max + + # bad + arr.sort_by(&:foo).first + arr.sort_by(&:foo)[0] + arr.sort_by(&:foo).at(0) + arr.sort_by(&:foo).slice(0) + + # good + arr.min_by(&:foo) + + # bad + arr.sort_by(&:foo).last + arr.sort_by(&:foo)[-1] + arr.sort_by(&:foo).at(-1) + arr.sort_by(&:foo).slice(-1) + + # good + arr.max_by(&:foo) diff --git a/config/contents/style/unpack_first.md b/config/contents/style/unpack_first.md new file mode 100644 index 00000000..86188e19 --- /dev/null +++ b/config/contents/style/unpack_first.md @@ -0,0 +1,13 @@ +This cop checks for accessing the first element of `String#unpack` +which can be replaced with the shorter method `unpack1`. + +### Example: + + # bad + 'foo'.unpack('h*').first + 'foo'.unpack('h*')[0] + 'foo'.unpack('h*').slice(0) + 'foo'.unpack('h*').at(0) + + # good + 'foo'.unpack1('h*') diff --git a/config/contents/style/yoda_condition.md b/config/contents/style/yoda_condition.md index 458b7e60..20abc90c 100644 --- a/config/contents/style/yoda_condition.md +++ b/config/contents/style/yoda_condition.md @@ -1,8 +1,8 @@ -This cop checks for Yoda conditions, i.e. comparison operations where -readability is reduced because the operands are not ordered the same -way as they would be ordered in spoken English. +This cop can either enforce or forbid Yoda conditions, +i.e. comparison operations where the order of expression is reversed. +eg. `5 == x` -### Example: EnforcedStyle: all_comparison_operators (default) +### Example: EnforcedStyle: forbid_for_all_comparison_operators (default) # bad 99 == foo "bar" != foo @@ -15,11 +15,33 @@ way as they would be ordered in spoken English. foo <= 42 bar > 10 -### Example: EnforcedStyle: equality_operators_only +### Example: EnforcedStyle: forbid_for_equality_operators_only # bad 99 == foo "bar" != foo # good 99 >= foo - 3 < a && a < 5 \ No newline at end of file + 3 < a && a < 5 + +### Example: EnforcedStyle: require_for_all_comparison_operators + # bad + foo == 99 + foo == "bar" + foo <= 42 + bar > 10 + + # good + 99 == foo + "bar" != foo + 42 >= foo + 10 < bar + +### Example: EnforcedStyle: require_for_equality_operators_only + # bad + 99 >= foo + 3 < a && a < 5 + + # good + 99 == foo + "bar" != foo \ No newline at end of file diff --git a/spec/support/currently_undocumented_cops.txt b/spec/support/currently_undocumented_cops.txt index 1a7c1b05..c1f98994 100644 --- a/spec/support/currently_undocumented_cops.txt +++ b/spec/support/currently_undocumented_cops.txt @@ -1,21 +1,8 @@ -RuboCop::Cop::Layout::EndOfLine -RuboCop::Cop::Layout::InitialIndentation -RuboCop::Cop::Layout::SpaceInsideBrackets -RuboCop::Cop::Layout::Tab -RuboCop::Cop::Layout::TrailingBlankLines -RuboCop::Cop::Layout::TrailingWhitespace +RuboCop::Cop::Layout::IndentFirstArgument RuboCop::Cop::Lint::MissingCopEnableDirective -RuboCop::Cop::Lint::ScriptPermission -RuboCop::Cop::Lint::Syntax RuboCop::Cop::Metrics::LineLength RuboCop::Cop::Performance::FixedSize -RuboCop::Cop::Rails::Validation -RuboCop::Cop::Style::BeginBlock RuboCop::Cop::Style::ConditionalAssignment -RuboCop::Cop::Style::Encoding -RuboCop::Cop::Style::EndBlock -RuboCop::Cop::Style::NegatedWhile -RuboCop::Cop::Style::NestedTernaryOperator -RuboCop::Cop::Style::OneLineConditional -RuboCop::Cop::Style::SpecialGlobalVars -RuboCop::Cop::Style::UnneededPercentQ +RuboCop::Cop::Style::MethodCallWithArgsParentheses + +