From 04c8e566731c521f8b31385e9f5cfd42e5ebbd46 Mon Sep 17 00:00:00 2001 From: John Pignata Date: Sat, 20 Feb 2016 11:23:06 -0500 Subject: [PATCH] Commit cop documentation Directly commits content from cop class documentation that at least provides an example or a description that isn't just a restatement of the check name or description. The motivation behind this change is to ensure that the content being exposed through the Code Climate service is useful and gives the user more details on how to resolve the issue being reported rather than restating a portion of the description. By directly committing the content this allows us to start supplementing the content from other sources such as the Ruby styleguide and our own original content. * Stop scraping content during the Docker image build * Scrape documentation from the current version of RuboCop * Modify regular expression to better target class documentation * Replace good/bad rdoc tokens with comments --- Dockerfile | 3 - config/contents/.gitignore | 1 - config/contents/lint/ambiguous_operator.md | 12 ++++ .../contents/lint/ambiguous_regexp_literal.md | 11 ++++ config/contents/lint/block_alignment.md | 8 +++ .../lint/circular_argument_reference.md | 30 +++++++++ config/contents/lint/condition_position.md | 9 +++ config/contents/lint/def_end_alignment.md | 13 ++++ config/contents/lint/duplicate_methods.md | 12 ++++ config/contents/lint/duplicated_key.md | 6 ++ .../lint/each_with_object_argument.md | 9 +++ config/contents/lint/else_layout.md | 11 ++++ config/contents/lint/empty_interpolation.md | 5 ++ config/contents/lint/end_alignment.md | 27 ++++++++ config/contents/lint/float_out_of_range.md | 10 +++ .../lint/format_parameter_mismatch.md | 7 +++ .../lint/implicit_string_concatenation.md | 14 +++++ .../lint/ineffective_access_modifier.md | 33 ++++++++++ .../lint/invalid_character_literal.md | 14 +++++ config/contents/lint/literal_in_condition.md | 13 ++++ .../contents/lint/literal_in_interpolation.md | 5 ++ .../contents/lint/nested_method_definition.md | 10 +++ .../contents/lint/next_without_accumulator.md | 14 +++++ .../lint/non_local_exit_from_iterator.md | 28 +++++++++ .../lint/parentheses_as_grouped_expression.md | 6 ++ config/contents/lint/rand_one.md | 13 ++++ config/contents/lint/require_parentheses.md | 14 +++++ .../string_conversion_in_interpolation.md | 6 ++ config/contents/lint/unused_block_argument.md | 7 +++ .../contents/lint/unused_method_argument.md | 7 +++ .../contents/lint/useless_access_modifier.md | 18 ++++++ config/contents/lint/useless_comparison.md | 5 ++ .../lint/useless_else_without_rescue.md | 8 +++ config/contents/lint/useless_setter_call.md | 9 +++ .../contents/metrics/cyclomatic_complexity.md | 10 +++ .../contents/metrics/perceived_complexity.md | 23 +++++++ .../contents/performance/case_when_splat.md | 47 ++++++++++++++ config/contents/performance/casecmp.md | 15 +++++ config/contents/performance/count.md | 20 ++++++ config/contents/performance/detect.md | 14 +++++ .../performance/double_start_end_with.md | 19 ++++++ config/contents/performance/end_with.md | 11 ++++ config/contents/performance/flat_map.md | 11 ++++ config/contents/performance/hash_each.md | 12 ++++ config/contents/performance/lstrip_rstrip.md | 10 +++ config/contents/performance/range_include.md | 10 +++ .../performance/redundant_block_call.md | 19 ++++++ .../contents/performance/redundant_match.md | 13 ++++ .../contents/performance/redundant_merge.md | 7 +++ .../contents/performance/redundant_sort_by.md | 12 ++++ config/contents/performance/reverse_each.md | 9 +++ config/contents/performance/sample.md | 21 +++++++ config/contents/performance/size.md | 20 ++++++ config/contents/performance/start_with.md | 11 ++++ .../performance/string_replacement.md | 15 +++++ config/contents/performance/times_map.md | 15 +++++ config/contents/rails/date.md | 32 ++++++++++ config/contents/rails/delegate.md | 25 ++++++++ config/contents/rails/find_by.md | 10 +++ config/contents/rails/find_each.md | 9 +++ .../contents/rails/pluralization_grammar.md | 11 ++++ config/contents/rails/read_write_attribute.md | 12 ++++ config/contents/rails/scope_args.md | 10 +++ config/contents/rails/time_zone.md | 24 +++++++ config/contents/style/accessor_method_name.md | 14 +++++ .../contents/style/auto_resource_cleanup.md | 13 ++++ config/contents/style/block_end_newline.md | 21 +++++++ config/contents/style/class_methods.md | 17 +++++ .../style/closing_parenthesis_indentation.md | 22 +++++++ config/contents/style/command_literal.md | 23 +++++++ config/contents/style/double_negation.md | 16 +++++ config/contents/style/each_with_object.md | 13 ++++ config/contents/style/empty_else.md | 62 +++++++++++++++++++ .../style/empty_lines_around_block_body.md | 9 +++ .../style/empty_lines_around_class_body.md | 12 ++++ .../style/empty_lines_around_method_body.md | 9 +++ .../style/empty_lines_around_module_body.md | 12 ++++ config/contents/style/even_odd.md | 10 +++ .../style/first_array_element_line_break.md | 13 ++++ .../style/first_hash_element_line_break.md | 13 ++++ .../style/first_method_argument_line_break.md | 17 +++++ .../first_method_parameter_line_break.md | 23 +++++++ .../style/first_parameter_indentation.md | 15 +++++ config/contents/style/guard_clause.md | 32 ++++++++++ .../style/identical_conditional_branches.md | 20 ++++++ config/contents/style/if_inside_else.md | 24 +++++++ config/contents/style/indent_assignment.md | 18 ++++++ .../contents/style/indentation_consistency.md | 10 +++ config/contents/style/indentation_width.md | 9 +++ config/contents/style/infinite_loop.md | 12 ++++ config/contents/style/lambda_call.md | 9 +++ .../contents/style/line_end_concatenation.md | 15 +++++ .../style/method_called_on_do_end_block.md | 9 +++ config/contents/style/missing_else.md | 25 ++++++++ config/contents/style/module_function.md | 9 +++ .../style/multiline_array_brace_layout.md | 33 ++++++++++ .../style/multiline_assignment_layout.md | 27 ++++++++ .../contents/style/multiline_block_chain.md | 10 +++ .../contents/style/multiline_block_layout.md | 32 ++++++++++ .../style/multiline_hash_brace_layout.md | 33 ++++++++++ config/contents/style/multiline_if_then.md | 12 ++++ .../multiline_method_call_brace_layout.md | 33 ++++++++++ .../multiline_method_call_indentation.md | 26 ++++++++ ...ultiline_method_definition_brace_layout.md | 37 +++++++++++ .../style/multiline_operation_indentation.md | 9 +++ config/contents/style/mutable_constant.md | 9 +++ config/contents/style/nested_modifier.md | 10 +++ .../style/nested_parenthesized_calls.md | 9 +++ config/contents/style/next.md | 15 +++++ config/contents/style/nil_comparison.md | 9 +++ config/contents/style/non_nil_check.md | 20 ++++++ config/contents/style/option_hash.md | 16 +++++ config/contents/style/optional_arguments.md | 14 +++++ config/contents/style/predicate_name.md | 14 +++++ config/contents/style/redundant_begin.md | 21 +++++++ config/contents/style/redundant_exception.md | 7 +++ config/contents/style/redundant_freeze.md | 8 +++ .../contents/style/redundant_parentheses.md | 9 +++ config/contents/style/redundant_return.md | 17 +++++ config/contents/style/redundant_self.md | 39 ++++++++++++ config/contents/style/regexp_literal.md | 25 ++++++++ .../contents/style/rescue_ensure_alignment.md | 18 ++++++ config/contents/style/self_assignment.md | 9 +++ .../contents/style/space_after_method_name.md | 9 +++ config/contents/style/space_after_not.md | 8 +++ .../style/space_around_block_parameters.md | 9 +++ config/contents/style/space_around_keyword.md | 21 +++++++ .../contents/style/space_before_first_arg.md | 11 ++++ .../style/space_inside_range_literal.md | 14 +++++ .../space_inside_string_interpolation.md | 8 +++ config/contents/style/struct_inheritance.md | 9 +++ config/contents/style/symbol_literal.md | 9 +++ config/contents/style/symbol_proc.md | 8 +++ .../style/trailing_comma_in_arguments.md | 23 +++++++ .../style/trailing_comma_in_literal.md | 23 +++++++ .../style/trailing_underscore_variable.md | 14 +++++ .../contents/style/unneeded_interpolation.md | 12 ++++ .../contents/style/zero_length_predicate.md | 16 +++++ lib/tasks/docs.rake | 9 ++- spec/cc/engine/issue_spec.rb | 16 ++--- spec/cc/engine/rubocop_spec.rb | 9 --- 141 files changed, 2127 insertions(+), 23 deletions(-) delete mode 100644 config/contents/.gitignore create mode 100644 config/contents/lint/ambiguous_operator.md create mode 100644 config/contents/lint/ambiguous_regexp_literal.md create mode 100644 config/contents/lint/block_alignment.md create mode 100644 config/contents/lint/circular_argument_reference.md create mode 100644 config/contents/lint/condition_position.md create mode 100644 config/contents/lint/def_end_alignment.md create mode 100644 config/contents/lint/duplicate_methods.md create mode 100644 config/contents/lint/duplicated_key.md create mode 100644 config/contents/lint/each_with_object_argument.md create mode 100644 config/contents/lint/else_layout.md create mode 100644 config/contents/lint/empty_interpolation.md create mode 100644 config/contents/lint/end_alignment.md create mode 100644 config/contents/lint/float_out_of_range.md create mode 100644 config/contents/lint/format_parameter_mismatch.md create mode 100644 config/contents/lint/implicit_string_concatenation.md create mode 100644 config/contents/lint/ineffective_access_modifier.md create mode 100644 config/contents/lint/invalid_character_literal.md create mode 100644 config/contents/lint/literal_in_condition.md create mode 100644 config/contents/lint/literal_in_interpolation.md create mode 100644 config/contents/lint/nested_method_definition.md create mode 100644 config/contents/lint/next_without_accumulator.md create mode 100644 config/contents/lint/non_local_exit_from_iterator.md create mode 100644 config/contents/lint/parentheses_as_grouped_expression.md create mode 100644 config/contents/lint/rand_one.md create mode 100644 config/contents/lint/require_parentheses.md create mode 100644 config/contents/lint/string_conversion_in_interpolation.md create mode 100644 config/contents/lint/unused_block_argument.md create mode 100644 config/contents/lint/unused_method_argument.md create mode 100644 config/contents/lint/useless_access_modifier.md create mode 100644 config/contents/lint/useless_comparison.md create mode 100644 config/contents/lint/useless_else_without_rescue.md create mode 100644 config/contents/lint/useless_setter_call.md create mode 100644 config/contents/metrics/cyclomatic_complexity.md create mode 100644 config/contents/metrics/perceived_complexity.md create mode 100644 config/contents/performance/case_when_splat.md create mode 100644 config/contents/performance/casecmp.md create mode 100644 config/contents/performance/count.md create mode 100644 config/contents/performance/detect.md create mode 100644 config/contents/performance/double_start_end_with.md create mode 100644 config/contents/performance/end_with.md create mode 100644 config/contents/performance/flat_map.md create mode 100644 config/contents/performance/hash_each.md create mode 100644 config/contents/performance/lstrip_rstrip.md create mode 100644 config/contents/performance/range_include.md create mode 100644 config/contents/performance/redundant_block_call.md create mode 100644 config/contents/performance/redundant_match.md create mode 100644 config/contents/performance/redundant_merge.md create mode 100644 config/contents/performance/redundant_sort_by.md create mode 100644 config/contents/performance/reverse_each.md create mode 100644 config/contents/performance/sample.md create mode 100644 config/contents/performance/size.md create mode 100644 config/contents/performance/start_with.md create mode 100644 config/contents/performance/string_replacement.md create mode 100644 config/contents/performance/times_map.md create mode 100644 config/contents/rails/date.md create mode 100644 config/contents/rails/delegate.md create mode 100644 config/contents/rails/find_by.md create mode 100644 config/contents/rails/find_each.md create mode 100644 config/contents/rails/pluralization_grammar.md create mode 100644 config/contents/rails/read_write_attribute.md create mode 100644 config/contents/rails/scope_args.md create mode 100644 config/contents/rails/time_zone.md create mode 100644 config/contents/style/accessor_method_name.md create mode 100644 config/contents/style/auto_resource_cleanup.md create mode 100644 config/contents/style/block_end_newline.md create mode 100644 config/contents/style/class_methods.md create mode 100644 config/contents/style/closing_parenthesis_indentation.md create mode 100644 config/contents/style/command_literal.md create mode 100644 config/contents/style/double_negation.md create mode 100644 config/contents/style/each_with_object.md create mode 100644 config/contents/style/empty_else.md create mode 100644 config/contents/style/empty_lines_around_block_body.md create mode 100644 config/contents/style/empty_lines_around_class_body.md create mode 100644 config/contents/style/empty_lines_around_method_body.md create mode 100644 config/contents/style/empty_lines_around_module_body.md create mode 100644 config/contents/style/even_odd.md create mode 100644 config/contents/style/first_array_element_line_break.md create mode 100644 config/contents/style/first_hash_element_line_break.md create mode 100644 config/contents/style/first_method_argument_line_break.md create mode 100644 config/contents/style/first_method_parameter_line_break.md create mode 100644 config/contents/style/first_parameter_indentation.md create mode 100644 config/contents/style/guard_clause.md create mode 100644 config/contents/style/identical_conditional_branches.md create mode 100644 config/contents/style/if_inside_else.md create mode 100644 config/contents/style/indent_assignment.md create mode 100644 config/contents/style/indentation_consistency.md create mode 100644 config/contents/style/indentation_width.md create mode 100644 config/contents/style/infinite_loop.md create mode 100644 config/contents/style/lambda_call.md create mode 100644 config/contents/style/line_end_concatenation.md create mode 100644 config/contents/style/method_called_on_do_end_block.md create mode 100644 config/contents/style/missing_else.md create mode 100644 config/contents/style/module_function.md create mode 100644 config/contents/style/multiline_array_brace_layout.md create mode 100644 config/contents/style/multiline_assignment_layout.md create mode 100644 config/contents/style/multiline_block_chain.md create mode 100644 config/contents/style/multiline_block_layout.md create mode 100644 config/contents/style/multiline_hash_brace_layout.md create mode 100644 config/contents/style/multiline_if_then.md create mode 100644 config/contents/style/multiline_method_call_brace_layout.md create mode 100644 config/contents/style/multiline_method_call_indentation.md create mode 100644 config/contents/style/multiline_method_definition_brace_layout.md create mode 100644 config/contents/style/multiline_operation_indentation.md create mode 100644 config/contents/style/mutable_constant.md create mode 100644 config/contents/style/nested_modifier.md create mode 100644 config/contents/style/nested_parenthesized_calls.md create mode 100644 config/contents/style/next.md create mode 100644 config/contents/style/nil_comparison.md create mode 100644 config/contents/style/non_nil_check.md create mode 100644 config/contents/style/option_hash.md create mode 100644 config/contents/style/optional_arguments.md create mode 100644 config/contents/style/predicate_name.md create mode 100644 config/contents/style/redundant_begin.md create mode 100644 config/contents/style/redundant_exception.md create mode 100644 config/contents/style/redundant_freeze.md create mode 100644 config/contents/style/redundant_parentheses.md create mode 100644 config/contents/style/redundant_return.md create mode 100644 config/contents/style/redundant_self.md create mode 100644 config/contents/style/regexp_literal.md create mode 100644 config/contents/style/rescue_ensure_alignment.md create mode 100644 config/contents/style/self_assignment.md create mode 100644 config/contents/style/space_after_method_name.md create mode 100644 config/contents/style/space_after_not.md create mode 100644 config/contents/style/space_around_block_parameters.md create mode 100644 config/contents/style/space_around_keyword.md create mode 100644 config/contents/style/space_before_first_arg.md create mode 100644 config/contents/style/space_inside_range_literal.md create mode 100644 config/contents/style/space_inside_string_interpolation.md create mode 100644 config/contents/style/struct_inheritance.md create mode 100644 config/contents/style/symbol_literal.md create mode 100644 config/contents/style/symbol_proc.md create mode 100644 config/contents/style/trailing_comma_in_arguments.md create mode 100644 config/contents/style/trailing_comma_in_literal.md create mode 100644 config/contents/style/trailing_underscore_variable.md create mode 100644 config/contents/style/unneeded_interpolation.md create mode 100644 config/contents/style/zero_length_predicate.md diff --git a/Dockerfile b/Dockerfile index c86ebefa..3ca1daa3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,9 +14,6 @@ RUN chown -R app:app /usr/src/app USER app -RUN cd /usr/src/app && \ - rake docs:scrape - VOLUME /code WORKDIR /code diff --git a/config/contents/.gitignore b/config/contents/.gitignore deleted file mode 100644 index dd449725..00000000 --- a/config/contents/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.md diff --git a/config/contents/lint/ambiguous_operator.md b/config/contents/lint/ambiguous_operator.md new file mode 100644 index 00000000..62dc2876 --- /dev/null +++ b/config/contents/lint/ambiguous_operator.md @@ -0,0 +1,12 @@ +This cop checks for ambiguous operators in the first argument of a +method invocation without parentheses. + +### Example: + array = [1, 2, 3] + + # The `*` is interpreted as a splat operator but it could possibly be + # a `*` method invocation (i.e. `do_something.*(array)`). + do_something *array + + # With parentheses, there's no ambiguity. + do_something(*array) \ No newline at end of file diff --git a/config/contents/lint/ambiguous_regexp_literal.md b/config/contents/lint/ambiguous_regexp_literal.md new file mode 100644 index 00000000..cbd59a4c --- /dev/null +++ b/config/contents/lint/ambiguous_regexp_literal.md @@ -0,0 +1,11 @@ +This cop checks for ambiguous regexp literals in the first argument of +a method invocation without parentheses. + +### Example: + # This is interpreted as a method invocation with a regexp literal, + # but it could possibly be `/` method invocations. + # (i.e. `do_something./(pattern)./(i)`) + do_something /pattern/i + + # With parentheses, there's no ambiguity. + do_something(/pattern/i) \ No newline at end of file diff --git a/config/contents/lint/block_alignment.md b/config/contents/lint/block_alignment.md new file mode 100644 index 00000000..11f2d970 --- /dev/null +++ b/config/contents/lint/block_alignment.md @@ -0,0 +1,8 @@ +This cop checks whether the end keywords are aligned properly for do +end blocks. + +### Example: + + variable = lambda do |i| + i + end \ No newline at end of file diff --git a/config/contents/lint/circular_argument_reference.md b/config/contents/lint/circular_argument_reference.md new file mode 100644 index 00000000..4bc805f7 --- /dev/null +++ b/config/contents/lint/circular_argument_reference.md @@ -0,0 +1,30 @@ +This cop checks for circular argument references in optional keyword +arguments and optional ordinal arguments. + +This cop mirrors a warning produced by MRI since 2.2. + +### Example: + # bad + def bake(pie: pie) + pie.heat_up + end + + # good + def bake(pie:) + pie.refrigerate + end + + # good + def bake(pie: self.pie) + pie.feed_to(user) + end + + # bad + def cook(dry_ingredients = dry_ingredients) + dry_ingredients.reduce(&:+) + end + + # good + def cook(dry_ingredients = self.dry_ingredients) + dry_ingredients.combine + end \ No newline at end of file diff --git a/config/contents/lint/condition_position.md b/config/contents/lint/condition_position.md new file mode 100644 index 00000000..153c29ac --- /dev/null +++ b/config/contents/lint/condition_position.md @@ -0,0 +1,9 @@ +This cop checks for conditions that are not on the same line as +if/while/until. + +### Example: + + if + some_condition + do_something + end \ No newline at end of file diff --git a/config/contents/lint/def_end_alignment.md b/config/contents/lint/def_end_alignment.md new file mode 100644 index 00000000..aed3fea8 --- /dev/null +++ b/config/contents/lint/def_end_alignment.md @@ -0,0 +1,13 @@ +This cop checks whether the end keywords of method definitions are +aligned properly. + +Two modes are supported through the AlignWith 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: + + private def foo + end \ No newline at end of file diff --git a/config/contents/lint/duplicate_methods.md b/config/contents/lint/duplicate_methods.md new file mode 100644 index 00000000..f210aafc --- /dev/null +++ b/config/contents/lint/duplicate_methods.md @@ -0,0 +1,12 @@ +This cop checks for duplicated instance (or singleton) method +definitions. + +### Example: + # bad + def duplicated + 1 + end + + def duplicated + 2 + end \ No newline at end of file diff --git a/config/contents/lint/duplicated_key.md b/config/contents/lint/duplicated_key.md new file mode 100644 index 00000000..6ec346f2 --- /dev/null +++ b/config/contents/lint/duplicated_key.md @@ -0,0 +1,6 @@ +This cop checks for duplicated keys in hash literals. + +This cop mirrors a warning in Ruby 2.2. + +### Example: + hash = { food: 'apple', food: 'orange' } \ No newline at end of file diff --git a/config/contents/lint/each_with_object_argument.md b/config/contents/lint/each_with_object_argument.md new file mode 100644 index 00000000..b2a37be4 --- /dev/null +++ b/config/contents/lint/each_with_object_argument.md @@ -0,0 +1,9 @@ +This cop checks if each_with_object is called with an immutable +argument. Since the argument is the object that the given block shall +make calls on to build something based on the enumerable that +each_with_object iterates over, an immutable argument makes no sense. +It's definitely a bug. + +### Example: + + sum = numbers.each_with_object(0) { |e, a| a += e } \ No newline at end of file diff --git a/config/contents/lint/else_layout.md b/config/contents/lint/else_layout.md new file mode 100644 index 00000000..23715628 --- /dev/null +++ b/config/contents/lint/else_layout.md @@ -0,0 +1,11 @@ +This cop checks for odd else block layout - like +having an expression on the same line as the else keyword, +which is usually a mistake. + +### Example: + + if something + ... + else do_this + do_that + end \ No newline at end of file diff --git a/config/contents/lint/empty_interpolation.md b/config/contents/lint/empty_interpolation.md new file mode 100644 index 00000000..f07b17f1 --- /dev/null +++ b/config/contents/lint/empty_interpolation.md @@ -0,0 +1,5 @@ +This cop checks for empty interpolation. + +### Example: + + "result is #{}" \ No newline at end of file diff --git a/config/contents/lint/end_alignment.md b/config/contents/lint/end_alignment.md new file mode 100644 index 00000000..cc8ca6b1 --- /dev/null +++ b/config/contents/lint/end_alignment.md @@ -0,0 +1,27 @@ +This cop checks whether the end keywords are aligned properly. + +Three modes are supported through the `AlignWith` 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: + # good + # keyword style + variable = if true + end + + # variable style + variable = if true + end + + # start_of_line style + puts(if true + end) \ No newline at end of file diff --git a/config/contents/lint/float_out_of_range.md b/config/contents/lint/float_out_of_range.md new file mode 100644 index 00000000..5da6a5ca --- /dev/null +++ b/config/contents/lint/float_out_of_range.md @@ -0,0 +1,10 @@ +This cop identifies Float literals which are, like, really really really +really really really really really big. Too big. No-one needs Floats +that big. If you need a float that big, something is wrong with you. + +### Example: + # bad + float = 3.0e400 + + # good + float = 42.9 \ No newline at end of file diff --git a/config/contents/lint/format_parameter_mismatch.md b/config/contents/lint/format_parameter_mismatch.md new file mode 100644 index 00000000..b66988b3 --- /dev/null +++ b/config/contents/lint/format_parameter_mismatch.md @@ -0,0 +1,7 @@ +This lint sees if there is a mismatch between the number of +expected fields for format/sprintf/#% and what is actually +passed as arguments. + +### Example: + + format('A value: %s and another: %i', a_value) diff --git a/config/contents/lint/implicit_string_concatenation.md b/config/contents/lint/implicit_string_concatenation.md new file mode 100644 index 00000000..e957b838 --- /dev/null +++ b/config/contents/lint/implicit_string_concatenation.md @@ -0,0 +1,14 @@ +This cop checks for implicit string concatenation of string literals +which are on the same line. + +### Example: + # bad + array = ['Item 1' 'Item 2'] + + # good + array = ['Item 1Item 2'] + array = ['Item 1' + 'Item 2'] + array = [ + 'Item 1' \ + 'Item 2' + ] \ No newline at end of file diff --git a/config/contents/lint/ineffective_access_modifier.md b/config/contents/lint/ineffective_access_modifier.md new file mode 100644 index 00000000..8238b25d --- /dev/null +++ b/config/contents/lint/ineffective_access_modifier.md @@ -0,0 +1,33 @@ +This cop checks for `private` or `protected` access modifiers which are +applied to a singleton method. These access modifiers do not make +singleton methods private/protected. `private_class_method` can be +used for that. + +### Example: + # bad + class C + private + + def self.method + puts 'hi' + end + end + + # good + class C + def self.method + puts 'hi' + end + + private_class_method :method + end + + class C + class << self + private + + def method + puts 'hi' + end + end + end \ No newline at end of file diff --git a/config/contents/lint/invalid_character_literal.md b/config/contents/lint/invalid_character_literal.md new file mode 100644 index 00000000..a4b42eba --- /dev/null +++ b/config/contents/lint/invalid_character_literal.md @@ -0,0 +1,14 @@ +This cop checks for invalid character literals with a non-escaped +whitespace character (e.g. `? `). +However, currently it's unclear whether there's a way to emit this +warning without syntax errors. + + $ ruby -w + p(? ) + -:1: warning: invalid character syntax; use ?\s + -:1: syntax error, unexpected '?', expecting ')' + p(? ) + ^ + +### Example: + p(? ) \ No newline at end of file diff --git a/config/contents/lint/literal_in_condition.md b/config/contents/lint/literal_in_condition.md new file mode 100644 index 00000000..622844dd --- /dev/null +++ b/config/contents/lint/literal_in_condition.md @@ -0,0 +1,13 @@ +This cop checks for literals used as the conditions or as +operands in and/or expressions serving as the conditions of +if/while/until. + +### Example: + + if 20 + do_something + end + + if some_var && true + do_something + end diff --git a/config/contents/lint/literal_in_interpolation.md b/config/contents/lint/literal_in_interpolation.md new file mode 100644 index 00000000..2d64b0a2 --- /dev/null +++ b/config/contents/lint/literal_in_interpolation.md @@ -0,0 +1,5 @@ +This cop checks for interpolated literals. + +### Example: + + "result is #{10}" \ No newline at end of file diff --git a/config/contents/lint/nested_method_definition.md b/config/contents/lint/nested_method_definition.md new file mode 100644 index 00000000..df93cb89 --- /dev/null +++ b/config/contents/lint/nested_method_definition.md @@ -0,0 +1,10 @@ +This cop checks for nested method definitions. + +### Example: + # `bar` definition actually produces methods in the same scope + # as the outer `foo` method. Furthermore, the `bar` method + # will be redefined every time `foo` is invoked. + def foo + def bar + end + end diff --git a/config/contents/lint/next_without_accumulator.md b/config/contents/lint/next_without_accumulator.md new file mode 100644 index 00000000..afa476c3 --- /dev/null +++ b/config/contents/lint/next_without_accumulator.md @@ -0,0 +1,14 @@ +Don't omit the accumulator when calling `next` in a `reduce` block. + +### Example: + # bad + result = (1..4).reduce(0) do |acc, i| + next if i.odd? + acc + i + end + + # good + result = (1..4).reduce(0) do |acc, i| + next acc if i.odd? + acc + i + end \ No newline at end of file diff --git a/config/contents/lint/non_local_exit_from_iterator.md b/config/contents/lint/non_local_exit_from_iterator.md new file mode 100644 index 00000000..e766289e --- /dev/null +++ b/config/contents/lint/non_local_exit_from_iterator.md @@ -0,0 +1,28 @@ +This cop checks for non-local exit from iterator, without return value. +It warns only when satisfies all of these: `return` doesn't have return +value, the block is preceded by a method chain, the block has arguments, +and the method which receives the block is not `define_method`. + +### Example: + + class ItemApi + rescue_from ValidationError do |e| # non-iteration block with arg + return message: 'validation error' unless e.errors # allowed + error_array = e.errors.map do |error| # block with method chain + return if error.suppress? # warned + return "#{error.param}: invalid" unless error.message # allowed + "#{error.param}: #{error.message}" + end + message: 'validation error', errors: error_array + end + + def update_items + transaction do # block without arguments + return unless update_necessary? # allowed + find_each do |item| # block without method chain + return if item.stock == 0 # false-negative... + item.update!(foobar: true) + end + end + end + end diff --git a/config/contents/lint/parentheses_as_grouped_expression.md b/config/contents/lint/parentheses_as_grouped_expression.md new file mode 100644 index 00000000..336f2db7 --- /dev/null +++ b/config/contents/lint/parentheses_as_grouped_expression.md @@ -0,0 +1,6 @@ +Checks for space between a the name of a called method and a left +parenthesis. + +### Example: + + puts (x + y) \ No newline at end of file diff --git a/config/contents/lint/rand_one.md b/config/contents/lint/rand_one.md new file mode 100644 index 00000000..4b9fcd04 --- /dev/null +++ b/config/contents/lint/rand_one.md @@ -0,0 +1,13 @@ +This cop checks for `rand(1)` calls. +Such calls always return `0`. + +### Example: + + # bad + rand 1 + Kernel.rand(-1) + rand 1.0 + rand(-1.0) + + # good + 0 \ No newline at end of file diff --git a/config/contents/lint/require_parentheses.md b/config/contents/lint/require_parentheses.md new file mode 100644 index 00000000..18ba6dc6 --- /dev/null +++ b/config/contents/lint/require_parentheses.md @@ -0,0 +1,14 @@ +This cop checks for expressions where there is a call to a predicate +method with at least one argument, where no parentheses are used around +the parameter list, and a boolean operator, && or ||, is used in the +last argument. + +The idea behind warning for these constructs is that the user might +be under the impression that the return value from the method call is +an operand of &&/||. + +### Example: + + if day.is? :tuesday && month == :jan + ... + end \ No newline at end of file diff --git a/config/contents/lint/string_conversion_in_interpolation.md b/config/contents/lint/string_conversion_in_interpolation.md new file mode 100644 index 00000000..d57c1973 --- /dev/null +++ b/config/contents/lint/string_conversion_in_interpolation.md @@ -0,0 +1,6 @@ +This cop checks for string conversion in string interpolation, +which is redundant. + +### Example: + + "result is #{something.to_s}" \ No newline at end of file diff --git a/config/contents/lint/unused_block_argument.md b/config/contents/lint/unused_block_argument.md new file mode 100644 index 00000000..a37db618 --- /dev/null +++ b/config/contents/lint/unused_block_argument.md @@ -0,0 +1,7 @@ +This cop checks for unused block arguments. + +### Example: + + do_something do |used, unused, _unused_but_allowed| + puts used + end \ No newline at end of file diff --git a/config/contents/lint/unused_method_argument.md b/config/contents/lint/unused_method_argument.md new file mode 100644 index 00000000..f7ffa118 --- /dev/null +++ b/config/contents/lint/unused_method_argument.md @@ -0,0 +1,7 @@ +This cop checks for unused method arguments. + +### Example: + + def some_method(used, unused, _unused_but_allowed) + puts used + end \ No newline at end of file diff --git a/config/contents/lint/useless_access_modifier.md b/config/contents/lint/useless_access_modifier.md new file mode 100644 index 00000000..2b1d67f2 --- /dev/null +++ b/config/contents/lint/useless_access_modifier.md @@ -0,0 +1,18 @@ +This cop checks for redundant access modifiers, including those with +no code, those which are repeated, and leading `public` modifiers in +a class or module body. + +### Example: + + class Foo + public # this is redundant + + def method + end + + private # this is not redundant + def method2 + end + + private # this is redundant + end \ No newline at end of file diff --git a/config/contents/lint/useless_comparison.md b/config/contents/lint/useless_comparison.md new file mode 100644 index 00000000..fa38ec62 --- /dev/null +++ b/config/contents/lint/useless_comparison.md @@ -0,0 +1,5 @@ +This cop checks for comparison of something with itself. + +### Example: + + x.top >= x.top \ No newline at end of file diff --git a/config/contents/lint/useless_else_without_rescue.md b/config/contents/lint/useless_else_without_rescue.md new file mode 100644 index 00000000..0eec0fef --- /dev/null +++ b/config/contents/lint/useless_else_without_rescue.md @@ -0,0 +1,8 @@ +This cop checks for useless `else` in `begin..end` without `rescue`. + +### Example: + begin + do_something + else + handle_errors # This will never be run. + end \ No newline at end of file diff --git a/config/contents/lint/useless_setter_call.md b/config/contents/lint/useless_setter_call.md new file mode 100644 index 00000000..239dfd5d --- /dev/null +++ b/config/contents/lint/useless_setter_call.md @@ -0,0 +1,9 @@ +This cop checks for setter call to local variable as the final +expression of a function definition. + +### Example: + + def something + x = Something.new + x.attr = 5 + end \ No newline at end of file diff --git a/config/contents/metrics/cyclomatic_complexity.md b/config/contents/metrics/cyclomatic_complexity.md new file mode 100644 index 00000000..7b977729 --- /dev/null +++ b/config/contents/metrics/cyclomatic_complexity.md @@ -0,0 +1,10 @@ +This cop checks that the cyclomatic complexity of methods is not higher +than the configured maximum. The cyclomatic complexity is the number of +linearly independent paths through a method. The algorithm counts +decision points and adds one. + +An if statement (or unless or ?:) increases the complexity by one. An +else branch does not, since it doesn't add a decision point. The && +operator (or keyword and) can be converted to a nested if statement, +and ||/or is shorthand for a sequence of ifs, so they also add one. +Loops can be said to have an exit condition, so they add one. \ No newline at end of file diff --git a/config/contents/metrics/perceived_complexity.md b/config/contents/metrics/perceived_complexity.md new file mode 100644 index 00000000..a384377b --- /dev/null +++ b/config/contents/metrics/perceived_complexity.md @@ -0,0 +1,23 @@ +This cop tries to produce a complexity score that's a measure of the +complexity the reader experiences when looking at a method. For that +reason it considers `when` nodes as something that doesn't add as much +complexity as an `if` or a `&&`. Except if it's one of those special +`case`/`when` constructs where there's no expression after `case`. Then +the cop treats it as an `if`/`elsif`/`elsif`... and lets all the `when` +nodes count. In contrast to the CyclomaticComplexity cop, this cop +considers `else` nodes as adding complexity. + +### Example: + + def my_method # 1 + if cond # 1 + case var # 2 (0.8 + 4 * 0.2, rounded) + when 1 then func_one + when 2 then func_two + when 3 then func_three + when 4..10 then func_other + end + else # 1 + do_something until a && b # 2 + end # === + end # 7 complexity points \ No newline at end of file diff --git a/config/contents/performance/case_when_splat.md b/config/contents/performance/case_when_splat.md new file mode 100644 index 00000000..0786e1da --- /dev/null +++ b/config/contents/performance/case_when_splat.md @@ -0,0 +1,47 @@ +Place `when` conditions that use splat at the end +of the list of `when` branches. + +Ruby has to allocate memory for the splat expansion every time +that the `case` `when` statement is run. Since Ruby does not support +fall through inside of `case` `when`, like some other languages do, +the order of the `when` branches does not matter. By placing any +splat expansions at the end of the list of `when` branches we will +reduce the number of times that memory has to be allocated for +the expansion. + +This is not a guaranteed performance improvement. If the data being +processed by the `case` condition is normalized in a manner that favors +hitting a condition in the splat expansion, it is possible that +moving the splat condition to the end will use more memory, +and run slightly slower. + +### Example: + # bad + case foo + when *condition + bar + when baz + foobar + end + + case foo + when *[1, 2, 3, 4] + bar + when 5 + baz + end + + # good + case foo + when baz + foobar + when *condition + bar + end + + case foo + when 1, 2, 3, 4 + bar + when 5 + baz + end \ No newline at end of file diff --git a/config/contents/performance/casecmp.md b/config/contents/performance/casecmp.md new file mode 100644 index 00000000..bb37e546 --- /dev/null +++ b/config/contents/performance/casecmp.md @@ -0,0 +1,15 @@ +This cop identifies places where a case-insensitive string comparison +can better be implemented using `casecmp`. + +### Example: + # bad + 'aBc'.downcase == 'abc' + 'abc'.upcase.eql? 'ABC' + 'abc' == 'ABC'.downcase + 'ABC'.eql? 'abc'.upcase + 'abc'.downcase == 'abc'.downcase + + # good + 'aBc'.casecmp('ABC').zero? + 'abc'.casecmp('abc').zero? + 'abc'.casecmp('ABC'.downcase).zero? \ No newline at end of file diff --git a/config/contents/performance/count.md b/config/contents/performance/count.md new file mode 100644 index 00000000..b8def54a --- /dev/null +++ b/config/contents/performance/count.md @@ -0,0 +1,20 @@ +This cop is used to identify usages of `count` on an +`Enumerable` and change them to `size`. + +### Example: + # bad + [1, 2, 3].select { |e| e > 2 }.size + [1, 2, 3].reject { |e| e > 2 }.size + [1, 2, 3].select { |e| e > 2 }.length + [1, 2, 3].reject { |e| e > 2 }.length + [1, 2, 3].select { |e| e > 2 }.count { |e| e.odd? } + [1, 2, 3].reject { |e| e > 2 }.count { |e| e.even? } + array.select(&:value).count + + # good + [1, 2, 3].count { |e| e > 2 } + [1, 2, 3].count { |e| e < 2 } + [1, 2, 3].count { |e| e > 2 && e.odd? } + [1, 2, 3].count { |e| e < 2 && e.even? } + Model.select('field AS field_one').count + Model.select(:value).count \ No newline at end of file diff --git a/config/contents/performance/detect.md b/config/contents/performance/detect.md new file mode 100644 index 00000000..946835ef --- /dev/null +++ b/config/contents/performance/detect.md @@ -0,0 +1,14 @@ +This cop is used to identify usages of +`select.first`, `select.last`, `find_all.first`, and `find_all.last` +and change them to use `detect` instead. + +### Example: + # bad + [].select { |item| true }.first + [].select { |item| true }.last + [].find_all { |item| true }.first + [].find_all { |item| true }.last + + # good + [].detect { |item| true } + [].reverse.detect { |item| true } \ No newline at end of file diff --git a/config/contents/performance/double_start_end_with.md b/config/contents/performance/double_start_end_with.md new file mode 100644 index 00000000..e43b8b58 --- /dev/null +++ b/config/contents/performance/double_start_end_with.md @@ -0,0 +1,19 @@ +This cop checks for double `#start_with?` or `#end_with?` calls +separated by `||`. In some cases such calls can be replaced +with an single `#start_with?`/`#end_with?` call. + +### Example: + + # bad + str.start_with?("a") || str.start_with?(Some::CONST) + str.start_with?("a", "b") || str.start_with?("c") + var1 = ... + var2 = ... + str.end_with?(var1) || str.end_with?(var2) + + # good + str.start_with?("a", Some::CONST) + str.start_with?("a", "b", "c") + var1 = ... + var2 = ... + str.end_with?(var1, var2) \ No newline at end of file diff --git a/config/contents/performance/end_with.md b/config/contents/performance/end_with.md new file mode 100644 index 00000000..d17db641 --- /dev/null +++ b/config/contents/performance/end_with.md @@ -0,0 +1,11 @@ +This cop identifies unnecessary use of a regex where `String#end_with?` +would suffice. + +### Example: + # bad + 'abc' =~ /bc\Z/ + 'abc'.match(/bc\Z/) + + # good + 'abc' =~ /ab/ + 'abc' =~ /\w*\Z/ \ No newline at end of file diff --git a/config/contents/performance/flat_map.md b/config/contents/performance/flat_map.md new file mode 100644 index 00000000..d6f8c0e6 --- /dev/null +++ b/config/contents/performance/flat_map.md @@ -0,0 +1,11 @@ +This cop is used to identify usages of + +### Example: + # bad + [1, 2, 3, 4].map { |e| [e, e] }.flatten(1) + [1, 2, 3, 4].collect { |e| [e, e] }.flatten(1) + + # good + [1, 2, 3, 4].flat_map { |e| [e, e] } + [1, 2, 3, 4].map { |e| [e, e] }.flatten + [1, 2, 3, 4].collect { |e| [e, e] }.flatten \ No newline at end of file diff --git a/config/contents/performance/hash_each.md b/config/contents/performance/hash_each.md new file mode 100644 index 00000000..7adb97a4 --- /dev/null +++ b/config/contents/performance/hash_each.md @@ -0,0 +1,12 @@ +This cop checks for uses of `each_key` & `each_value` Hash methods. + +### Example: + # bad + hash.keys.each { |k| p k } + hash.values.each { |v| p v } + hash.each { |k, _v| p k } + hash.each { |_k, v| p v } + + # good + hash.each_key { |k| p k } + hash.each_value { |v| p v } \ No newline at end of file diff --git a/config/contents/performance/lstrip_rstrip.md b/config/contents/performance/lstrip_rstrip.md new file mode 100644 index 00000000..20f263b1 --- /dev/null +++ b/config/contents/performance/lstrip_rstrip.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/performance/range_include.md b/config/contents/performance/range_include.md new file mode 100644 index 00000000..7833df33 --- /dev/null +++ b/config/contents/performance/range_include.md @@ -0,0 +1,10 @@ +This cop identifies uses of `Range#include?`, which iterates over each +item in a `Range` to see if a specified item is there. In contrast, +`Range#cover?` simply compares the target item with the beginning and +end points of the `Range`. In a great majority of cases, this is what +is wanted. + +Here is an example of a case where `Range#cover?` may not provide the +desired result: + + ('a'..'z').cover?('yellow') # => true diff --git a/config/contents/performance/redundant_block_call.md b/config/contents/performance/redundant_block_call.md new file mode 100644 index 00000000..8dae752c --- /dev/null +++ b/config/contents/performance/redundant_block_call.md @@ -0,0 +1,19 @@ +This cop identifies the use of a `&block` parameter and `block.call` +where `yield` would do just as well. + +### Example: + # bad + def method(&block) + block.call + end + def another(&func) + func.call 1, 2, 3 + end + + # good + def method + yield + end + def another + yield 1, 2, 3 + end \ No newline at end of file diff --git a/config/contents/performance/redundant_match.md b/config/contents/performance/redundant_match.md new file mode 100644 index 00000000..d6645bdd --- /dev/null +++ b/config/contents/performance/redundant_match.md @@ -0,0 +1,13 @@ +This cop identifies use of `Regexp#match` or `String#match in a context +where the integral return value of `=~` would do just as well. + +### Example: + # bad + do_something if str.match(/regex/) + while regex.match('str') + do_something + end + + # good + method(str.match(/regex/)) + return regex.match('str') \ No newline at end of file diff --git a/config/contents/performance/redundant_merge.md b/config/contents/performance/redundant_merge.md new file mode 100644 index 00000000..1df2002b --- /dev/null +++ b/config/contents/performance/redundant_merge.md @@ -0,0 +1,7 @@ +This cop identifies places where `Hash#merge!` can be replaced by +`Hash#[]=`. + +### Example: + hash.merge!(a: 1) + hash.merge!({'key' => 'value'}) + hash.merge!(a: 1, b: 2) \ No newline at end of file diff --git a/config/contents/performance/redundant_sort_by.md b/config/contents/performance/redundant_sort_by.md new file mode 100644 index 00000000..a03586dc --- /dev/null +++ b/config/contents/performance/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/performance/reverse_each.md b/config/contents/performance/reverse_each.md new file mode 100644 index 00000000..58d5405c --- /dev/null +++ b/config/contents/performance/reverse_each.md @@ -0,0 +1,9 @@ +This cop is used to identify usages of `reverse.each` and +change them to use `reverse_each` instead. + +### Example: + # bad + [].reverse.each + + # good + [].reverse_each \ No newline at end of file diff --git a/config/contents/performance/sample.md b/config/contents/performance/sample.md new file mode 100644 index 00000000..99a049e7 --- /dev/null +++ b/config/contents/performance/sample.md @@ -0,0 +1,21 @@ +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 + [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/performance/size.md b/config/contents/performance/size.md new file mode 100644 index 00000000..c3b03af9 --- /dev/null +++ b/config/contents/performance/size.md @@ -0,0 +1,20 @@ +This cop is used to identify usages of `count` on an +`Array` and `Hash` and change them to `size`. + +### Example: + # bad + [1, 2, 3].count + + # bad + {a: 1, b: 2, c: 3}.count + + # good + [1, 2, 3].size + + # good + {a: 1, b: 2, c: 3}.size + + # good + [1, 2, 3].count { |e| e > 2 } +TODO: Add advanced detection of variables that could +have been assigned to an array or a hash. \ No newline at end of file diff --git a/config/contents/performance/start_with.md b/config/contents/performance/start_with.md new file mode 100644 index 00000000..2ab24a29 --- /dev/null +++ b/config/contents/performance/start_with.md @@ -0,0 +1,11 @@ +This cop identifies unnecessary use of a regex where +`String#start_with?` would suffice. + +### Example: + # bad + 'abc' =~ /\Aab/ + 'abc'.match(/\Aab/) + + # good + 'abc' =~ /ab/ + 'abc' =~ /\A\w*/ \ No newline at end of file diff --git a/config/contents/performance/string_replacement.md b/config/contents/performance/string_replacement.md new file mode 100644 index 00000000..eed79736 --- /dev/null +++ b/config/contents/performance/string_replacement.md @@ -0,0 +1,15 @@ +This cop identifies places where `gsub` can be replaced by +`tr` or `delete`. + +### Example: + # bad + 'abc'.gsub('b', 'd') + 'abc'.gsub('a', '') + 'abc'.gsub(/a/, 'd') + 'abc'.gsub!('a', 'd') + + # good + 'abc'.gsub(/.*/, 'a') + 'abc'.gsub(/a+/, 'd') + 'abc'.tr('b', 'd') + 'a b c'.delete(' ') \ No newline at end of file diff --git a/config/contents/performance/times_map.md b/config/contents/performance/times_map.md new file mode 100644 index 00000000..6910ed01 --- /dev/null +++ b/config/contents/performance/times_map.md @@ -0,0 +1,15 @@ +This cop checks for .times.map calls. +In most cases such calls can be replaced +with an explicit array creation. + +### Example: + + # bad + 9.times.map do |i| + i.to_s + end + + # good + Array.new(9) do |i| + i.to_s + end \ No newline at end of file diff --git a/config/contents/rails/date.md b/config/contents/rails/date.md new file mode 100644 index 00000000..a8a156ac --- /dev/null +++ b/config/contents/rails/date.md @@ -0,0 +1,32 @@ +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. + +The cop also reports warnings when you are using 'to_time' method, +because it doesn't know about Rails time zone too. + +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. + +When EnforcedStyle is 'flexible' then only 'Date.today' is prohibited +and only 'to_time' is reported as warning. + +### Example: + # no offense + Time.zone.today + Time.zone.today - 1.day + + # acceptable + Date.current + Date.yesterday + + # always reports offense + Date.today + date.to_time + + # reports offense only when style is 'strict' + date.to_time_in_current_zone \ No newline at end of file diff --git a/config/contents/rails/delegate.md b/config/contents/rails/delegate.md new file mode 100644 index 00000000..3741c1f3 --- /dev/null +++ b/config/contents/rails/delegate.md @@ -0,0 +1,25 @@ +This cop looks for delegations, that could have been created +automatically with delegate method. + +### Example: + # bad + def bar + foo.bar + end + + # good + delegate :bar, to: :foo + + # bad + def foo_bar + foo.bar + end + + # good + delegate :bar, to: :foo, prefix: true + + # good + private + def bar + foo.bar + end \ No newline at end of file diff --git a/config/contents/rails/find_by.md b/config/contents/rails/find_by.md new file mode 100644 index 00000000..b53b15b8 --- /dev/null +++ b/config/contents/rails/find_by.md @@ -0,0 +1,10 @@ +This cop is used to identify usages of `where.first` and +change them to use `find_by` instead. + +### Example: + # bad + User.where(name: 'Bruce').first + User.where(name: 'Bruce').take + + # good + User.find_by(name: 'Bruce') \ No newline at end of file diff --git a/config/contents/rails/find_each.md b/config/contents/rails/find_each.md new file mode 100644 index 00000000..24a8566f --- /dev/null +++ b/config/contents/rails/find_each.md @@ -0,0 +1,9 @@ +This cop is used to identify usages of `all.each` and +change them to use `all.find_each` instead. + +### Example: + # bad + User.all.each + + # good + User.all.find_each \ No newline at end of file diff --git a/config/contents/rails/pluralization_grammar.md b/config/contents/rails/pluralization_grammar.md new file mode 100644 index 00000000..a1728c00 --- /dev/null +++ b/config/contents/rails/pluralization_grammar.md @@ -0,0 +1,11 @@ +This cop checks for correct grammar when using ActiveSupport's +core extensions to the numeric classes. + +### Example: + # bad + 3.day.ago + 1.months.ago + + # good + 3.days.ago + 1.month.ago \ No newline at end of file diff --git a/config/contents/rails/read_write_attribute.md b/config/contents/rails/read_write_attribute.md new file mode 100644 index 00000000..5aa4ed8f --- /dev/null +++ b/config/contents/rails/read_write_attribute.md @@ -0,0 +1,12 @@ +This cop checks for the use of the read_attribute or +write_attribute methods. + +### Example: + + # bad + x = read_attributed(:attr) + write_attribute(:attr, val) + + # good + x = self[:attr] + self[:attr] = val \ No newline at end of file diff --git a/config/contents/rails/scope_args.md b/config/contents/rails/scope_args.md new file mode 100644 index 00000000..10b4119c --- /dev/null +++ b/config/contents/rails/scope_args.md @@ -0,0 +1,10 @@ +This cop checks for scope calls where it was passed +a method (usually a scope) instead of a lambda/proc. + +### Example: + + # bad + scope :something, where(something: true) + + # good + scope :something, -> { where(something: true) } \ No newline at end of file diff --git a/config/contents/rails/time_zone.md b/config/contents/rails/time_zone.md new file mode 100644 index 00000000..c97d2871 --- /dev/null +++ b/config/contents/rails/time_zone.md @@ -0,0 +1,24 @@ +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) +and the article http://danilenko.org/2012/7/6/rails_timezones/ . + +Two styles are supported for this cop. When EnforcedStyle is 'strict' +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 + Time.now + Time.parse('2015-03-02 19:05:37') + + # no offense + Time.zone.now + Time.zone.parse('2015-03-02 19:05:37') + + # no offense only if style is 'acceptable' + 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/style/accessor_method_name.md b/config/contents/style/accessor_method_name.md new file mode 100644 index 00000000..eed86128 --- /dev/null +++ b/config/contents/style/accessor_method_name.md @@ -0,0 +1,14 @@ +This cop makes sure that accessor methods are named properly. + +### Example: + # bad + def set_attribute(value) ... + + # good + def attribute=(value) + + # bad + def get_attribute ... + + # good + def attribute ... \ No newline at end of file diff --git a/config/contents/style/auto_resource_cleanup.md b/config/contents/style/auto_resource_cleanup.md new file mode 100644 index 00000000..87d35ddc --- /dev/null +++ b/config/contents/style/auto_resource_cleanup.md @@ -0,0 +1,13 @@ +This cop checks for cases when you could use a block +accepting version of a method that does automatic +resource cleanup. + +### Example: + + # bad + f = File.open('file') + + # good + f = File.open('file') do + ... + end \ No newline at end of file diff --git a/config/contents/style/block_end_newline.md b/config/contents/style/block_end_newline.md new file mode 100644 index 00000000..ef2285ca --- /dev/null +++ b/config/contents/style/block_end_newline.md @@ -0,0 +1,21 @@ +This cop checks whether the end statement of a do..end block +is on its own line. + +### Example: + # bad + blah do |i| + foo(i) end + + # good + blah do |i| + foo(i) + end + + # bad + blah { |i| + foo(i) } + + # good + blah { |i| + foo(i) + } \ No newline at end of file diff --git a/config/contents/style/class_methods.md b/config/contents/style/class_methods.md new file mode 100644 index 00000000..3d12ebd2 --- /dev/null +++ b/config/contents/style/class_methods.md @@ -0,0 +1,17 @@ +This cop checks for uses of the class/module name instead of +self, when defining class/module methods. + +### Example: + # bad + class SomeClass + def SomeClass.class_method + ... + end + end + + # good + class SomeClass + def self.class_method + ... + end + end \ No newline at end of file diff --git a/config/contents/style/closing_parenthesis_indentation.md b/config/contents/style/closing_parenthesis_indentation.md new file mode 100644 index 00000000..9a47a7e2 --- /dev/null +++ b/config/contents/style/closing_parenthesis_indentation.md @@ -0,0 +1,22 @@ +This cops 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 + ) + + # good: when x follows opening parenthesis, align parentheses + a = b * (x + + y + ) + + # bad + def func( + x, + y + ) \ No newline at end of file diff --git a/config/contents/style/command_literal.md b/config/contents/style/command_literal.md new file mode 100644 index 00000000..81b16f3e --- /dev/null +++ b/config/contents/style/command_literal.md @@ -0,0 +1,23 @@ +This cop enforces using `` or %x around command literals. + +### Example: + # Good if EnforcedStyle is backticks or mixed, bad if percent_x. + folders = `find . -type d`.split + + # Good if EnforcedStyle is percent_x, bad if backticks or mixed. + folders = %x(find . -type d).split + + # Good if EnforcedStyle is backticks, bad if percent_x or mixed. + ` + ln -s foo.example.yml foo.example + ln -s bar.example.yml bar.example + ` + + # Good if EnforcedStyle is percent_x or mixed, bad if backticks. + %x( + ln -s foo.example.yml foo.example + ln -s bar.example.yml bar.example + ) + + # Bad unless AllowInnerBackticks is true. + `echo \`ls\`` \ No newline at end of file diff --git a/config/contents/style/double_negation.md b/config/contents/style/double_negation.md new file mode 100644 index 00000000..0d84a037 --- /dev/null +++ b/config/contents/style/double_negation.md @@ -0,0 +1,16 @@ +This cop checks for uses of double negation (!!) to convert something +to a boolean value. As this is both cryptic and usually redundant, it +should be avoided. + +### Example: + + # bad + !!something + + # good + !something.nil? + +Please, note that when something is a boolean value +!!something and !something.nil? are not the same thing. +As you're unlikely to write code that can accept values of any type +this is rarely a problem in practice. \ No newline at end of file diff --git a/config/contents/style/each_with_object.md b/config/contents/style/each_with_object.md new file mode 100644 index 00000000..2ef91aca --- /dev/null +++ b/config/contents/style/each_with_object.md @@ -0,0 +1,13 @@ +This cop looks for inject / reduce calls where the passed in object is +returned at the end and so could be replaced by each_with_object without +the need to return the object at the end. + +However, we can't replace with each_with_object if the accumulator +parameter is assigned to within the block. + +### Example: + # bad + [1, 2].inject({}) { |a, e| a[e] = e; a } + + # good + [1, 2].each_with_object({}) { |e, a| a[e] = e } \ No newline at end of file diff --git a/config/contents/style/empty_else.md b/config/contents/style/empty_else.md new file mode 100644 index 00000000..71a02788 --- /dev/null +++ b/config/contents/style/empty_else.md @@ -0,0 +1,62 @@ +Checks for empty else-clauses, possibly including comments and/or an +explicit `nil` depending on the EnforcedStyle. + +SupportedStyles: + +### Example: + # good for all styles + if condition + statement + else + statement + end + + # good for all styles + if condition + statement + end + +empty - warn only on empty else + ### Example: + # bad + if condition + statement + else + end + + # good + if condition + statement + else + nil + end + +nil - warn on else with nil in it + ### Example: + # bad + if condition + statement + else + nil + end + + # good + if condition + statement + else + end + +both - warn on empty else and else with nil in it + ### Example: + # bad + if condition + statement + else + nil + end + + # bad + if condition + statement + else + end \ No newline at end of file diff --git a/config/contents/style/empty_lines_around_block_body.md b/config/contents/style/empty_lines_around_block_body.md new file mode 100644 index 00000000..8a9d7a15 --- /dev/null +++ b/config/contents/style/empty_lines_around_block_body.md @@ -0,0 +1,9 @@ +This cops checks if empty lines around the bodies of blocks match +the configuration. + +### Example: + + something do + + ... + end diff --git a/config/contents/style/empty_lines_around_class_body.md b/config/contents/style/empty_lines_around_class_body.md new file mode 100644 index 00000000..a512a9b3 --- /dev/null +++ b/config/contents/style/empty_lines_around_class_body.md @@ -0,0 +1,12 @@ +This cops checks if empty lines around the bodies of classes match the +configuration. + +### Example: + + class Test + + def something + ... + end + + end diff --git a/config/contents/style/empty_lines_around_method_body.md b/config/contents/style/empty_lines_around_method_body.md new file mode 100644 index 00000000..a62dcf3d --- /dev/null +++ b/config/contents/style/empty_lines_around_method_body.md @@ -0,0 +1,9 @@ +This cops checks if empty lines around the bodies of methods match +the configuration. + +### Example: + + def something(arg) + + ... + end diff --git a/config/contents/style/empty_lines_around_module_body.md b/config/contents/style/empty_lines_around_module_body.md new file mode 100644 index 00000000..f750369e --- /dev/null +++ b/config/contents/style/empty_lines_around_module_body.md @@ -0,0 +1,12 @@ +This cops checks if empty lines around the bodies of modules match +the configuration. + +### Example: + + module Test + + def something + ... + end + + end diff --git a/config/contents/style/even_odd.md b/config/contents/style/even_odd.md new file mode 100644 index 00000000..6db1008c --- /dev/null +++ b/config/contents/style/even_odd.md @@ -0,0 +1,10 @@ +This cop checks for places where Fixnum#even? or Fixnum#odd? +should have been used. + +### Example: + + # bad + if x % 2 == 0 + + # good + if x.even? \ No newline at end of file diff --git a/config/contents/style/first_array_element_line_break.md b/config/contents/style/first_array_element_line_break.md new file mode 100644 index 00000000..93e82898 --- /dev/null +++ b/config/contents/style/first_array_element_line_break.md @@ -0,0 +1,13 @@ +This cop checks for a line break before the first element in a +multi-line array. + +### Example: + + # bad + [ :a, + :b] + + # good + [ + :a, + :b] diff --git a/config/contents/style/first_hash_element_line_break.md b/config/contents/style/first_hash_element_line_break.md new file mode 100644 index 00000000..fa3fa2d4 --- /dev/null +++ b/config/contents/style/first_hash_element_line_break.md @@ -0,0 +1,13 @@ +This cop checks for a line break before the first element in a +multi-line hash. + +### Example: + + # bad + { a: 1, + b: 2} + + # good + { + a: 1, + b: 2 } \ No newline at end of file diff --git a/config/contents/style/first_method_argument_line_break.md b/config/contents/style/first_method_argument_line_break.md new file mode 100644 index 00000000..e79ede51 --- /dev/null +++ b/config/contents/style/first_method_argument_line_break.md @@ -0,0 +1,17 @@ +This cop checks for a line break before the first argument in a +multi-line method call. + +### Example: + + # bad + method(foo, bar, + baz) + + # good + method( + foo, bar, + baz) + + # ignored + method foo, bar, + baz \ No newline at end of file diff --git a/config/contents/style/first_method_parameter_line_break.md b/config/contents/style/first_method_parameter_line_break.md new file mode 100644 index 00000000..165623fd --- /dev/null +++ b/config/contents/style/first_method_parameter_line_break.md @@ -0,0 +1,23 @@ +This cop checks for a line break before the first parameter in a +multi-line method parameter definition. + +### Example: + + # bad + def method(foo, bar, + baz) + do_something + end + + # good + def method( + foo, bar, + baz) + do_something + end + + # ignored + def method foo, + bar + do_something + end \ No newline at end of file diff --git a/config/contents/style/first_parameter_indentation.md b/config/contents/style/first_parameter_indentation.md new file mode 100644 index 00000000..cd4dc6f0 --- /dev/null +++ b/config/contents/style/first_parameter_indentation.md @@ -0,0 +1,15 @@ +This cop checks the indentation of the first parameter in a method call. +Parameters after the first one are checked by Style/AlignParameters, not +by this cop. + +### Example: + + # bad + some_method( + first_param, + second_param) + + # good + some_method( + first_param, + second_param) \ No newline at end of file diff --git a/config/contents/style/guard_clause.md b/config/contents/style/guard_clause.md new file mode 100644 index 00000000..00725de9 --- /dev/null +++ b/config/contents/style/guard_clause.md @@ -0,0 +1,32 @@ +Use a guard clause instead of wrapping the code inside a conditional +expression + +### Example: + # bad + def test + if something + work + end + end + + # good + def test + return unless something + work + end + + # also good + def test + work if something + end + + # bad + if something + raise 'exception' + else + ok + end + + # good + raise 'exception' if something + ok \ No newline at end of file diff --git a/config/contents/style/identical_conditional_branches.md b/config/contents/style/identical_conditional_branches.md new file mode 100644 index 00000000..5fe141c2 --- /dev/null +++ b/config/contents/style/identical_conditional_branches.md @@ -0,0 +1,20 @@ +This cop checks for identical lines at the end of each branch of a +conditional statement. + +### Example: + # bad + if condition + do_x + do_z + else + do_y + do_z + end + + # good + if condition + do_x + else + do_y + end + do_z \ No newline at end of file diff --git a/config/contents/style/if_inside_else.md b/config/contents/style/if_inside_else.md new file mode 100644 index 00000000..5227d145 --- /dev/null +++ b/config/contents/style/if_inside_else.md @@ -0,0 +1,24 @@ +If the `else` branch of a conditional consists solely of an `if` node, +it can be combined with the `else` to become an `elsif`. +This helps to keep the nesting level from getting too deep. + +### Example: + # good + if condition_a + action_a + elsif condition_b + action_b + else + action_c + end + + # bad + if condition_a + action_a + else + if condition_b + action_b + else + action_c + end + end \ No newline at end of file diff --git a/config/contents/style/indent_assignment.md b/config/contents/style/indent_assignment.md new file mode 100644 index 00000000..873b5f9d --- /dev/null +++ b/config/contents/style/indent_assignment.md @@ -0,0 +1,18 @@ +This cop checks the indentation of the first line of the +right-hand-side of a multi-line assignment. + +### Example: + # bad + value = + if foo + 'bar' + end + + # good + value = + if foo + 'bar' + end + +The indentation of the remaining lines can be corrected with +other cops such as `IndentationConsistency` and `EndAlignment`. \ No newline at end of file diff --git a/config/contents/style/indentation_consistency.md b/config/contents/style/indentation_consistency.md new file mode 100644 index 00000000..82c3b002 --- /dev/null +++ b/config/contents/style/indentation_consistency.md @@ -0,0 +1,10 @@ +This cops checks for inconsistent indentation. + +### Example: + + class A + def test + puts 'hello' + puts 'world' + end + end \ No newline at end of file diff --git a/config/contents/style/indentation_width.md b/config/contents/style/indentation_width.md new file mode 100644 index 00000000..e19274bf --- /dev/null +++ b/config/contents/style/indentation_width.md @@ -0,0 +1,9 @@ +This cops checks for indentation that doesn't use two spaces. + +### Example: + + class A + def test + puts 'hello' + end + end \ No newline at end of file diff --git a/config/contents/style/infinite_loop.md b/config/contents/style/infinite_loop.md new file mode 100644 index 00000000..22357ac2 --- /dev/null +++ b/config/contents/style/infinite_loop.md @@ -0,0 +1,12 @@ +Use `Kernel#loop` for infinite loops. + +### Example: + # bad + while true + work + end + + # good + loop do + work + end \ No newline at end of file diff --git a/config/contents/style/lambda_call.md b/config/contents/style/lambda_call.md new file mode 100644 index 00000000..4c4cdae5 --- /dev/null +++ b/config/contents/style/lambda_call.md @@ -0,0 +1,9 @@ +This cop checks for use of the lambda.(args) syntax. + +### Example: + + # bad + lambda.(x, y) + + # good + lambda.call(x, y) \ No newline at end of file diff --git a/config/contents/style/line_end_concatenation.md b/config/contents/style/line_end_concatenation.md new file mode 100644 index 00000000..9faec2e2 --- /dev/null +++ b/config/contents/style/line_end_concatenation.md @@ -0,0 +1,15 @@ +This cop checks for string literal concatenation at +the end of a line. + +### Example: + + # bad + some_str = 'ala' + + 'bala' + + some_str = 'ala' << + 'bala' + + # good + some_str = 'ala' \ + 'bala' diff --git a/config/contents/style/method_called_on_do_end_block.md b/config/contents/style/method_called_on_do_end_block.md new file mode 100644 index 00000000..6a254906 --- /dev/null +++ b/config/contents/style/method_called_on_do_end_block.md @@ -0,0 +1,9 @@ +This cop checks for methods called on a do...end block. The point of +this check is that it's easy to miss the call tacked on to the block +when reading code. + +### Example: + + a do + b + end.c \ No newline at end of file diff --git a/config/contents/style/missing_else.md b/config/contents/style/missing_else.md new file mode 100644 index 00000000..addee86b --- /dev/null +++ b/config/contents/style/missing_else.md @@ -0,0 +1,25 @@ +Checks for `if` expressions that do not have an `else` branch. +SupportedStyles + +if +### Example: + # bad + if condition + statement + end + +case +### Example: + # bad + case var + when condition + statement + end + +### Example: + # good + if condition + statement + else + # the content of the else branch will be determined by Style/EmptyElse + end \ No newline at end of file diff --git a/config/contents/style/module_function.md b/config/contents/style/module_function.md new file mode 100644 index 00000000..9e807f8e --- /dev/null +++ b/config/contents/style/module_function.md @@ -0,0 +1,9 @@ +This cops checks for use of `extend self` in a module. + +### Example: + + module Test + extend self + + ... +end \ No newline at end of file diff --git a/config/contents/style/multiline_array_brace_layout.md b/config/contents/style/multiline_array_brace_layout.md new file mode 100644 index 00000000..f305c599 --- /dev/null +++ b/config/contents/style/multiline_array_brace_layout.md @@ -0,0 +1,33 @@ +This cop checks that the closing brace in an array literal is +symmetrical with respect to the opening brace and the array +elements. + +If an array's opening brace is on the same line as the first element +of the array, then the closing brace should be on the same line as +the last element of the array. + +If an array's opening brace is on a separate line from the first +element of the array, then the closing brace should be on the line +after the last element of the array. + +### Example: + + # bad + [ :a, + :b + ] + + # bad + [ + :a, + :b ] + + # good + [ :a, + :b ] + + #good + [ + :a, + :b + ] \ No newline at end of file diff --git a/config/contents/style/multiline_assignment_layout.md b/config/contents/style/multiline_assignment_layout.md new file mode 100644 index 00000000..47052aea --- /dev/null +++ b/config/contents/style/multiline_assignment_layout.md @@ -0,0 +1,27 @@ +This cop checks whether the multiline assignments have a newline +after the assignment operator. + +### Example: + # bad (with EnforcedStyle set to new_line) + foo = if expression + 'bar' + end + + # good (with EnforcedStyle set to same_line) + foo = if expression + 'bar' + end + + # good (with EnforcedStyle set to new_line) + foo = + if expression + 'bar' + end + + # good (with EnforcedStyle set to new_line) + foo = + begin + compute + rescue => e + nil + end \ No newline at end of file diff --git a/config/contents/style/multiline_block_chain.md b/config/contents/style/multiline_block_chain.md new file mode 100644 index 00000000..d0eb6576 --- /dev/null +++ b/config/contents/style/multiline_block_chain.md @@ -0,0 +1,10 @@ +This cop checks for chaining of a block after another block that spans +multiple lines. + +### Example: + + Thread.list.find_all do |t| + t.alive? + end.map do |t| + t.object_id + end \ No newline at end of file diff --git a/config/contents/style/multiline_block_layout.md b/config/contents/style/multiline_block_layout.md new file mode 100644 index 00000000..7a28a3d8 --- /dev/null +++ b/config/contents/style/multiline_block_layout.md @@ -0,0 +1,32 @@ +This cop checks whether the multiline do end blocks have a newline +after the start of the block. Additionally, it checks whether the block +arguments, if any, are on the same line as the start of the block. + +### Example: + # bad + blah do |i| foo(i) + bar(i) + end + + # bad + blah do + |i| foo(i) + bar(i) + end + + # good + blah do |i| + foo(i) + bar(i) + end + + # bad + blah { |i| foo(i) + bar(i) + } + + # good + blah { |i| + foo(i) + bar(i) + } \ No newline at end of file diff --git a/config/contents/style/multiline_hash_brace_layout.md b/config/contents/style/multiline_hash_brace_layout.md new file mode 100644 index 00000000..47892826 --- /dev/null +++ b/config/contents/style/multiline_hash_brace_layout.md @@ -0,0 +1,33 @@ +This cop checks that the closing brace in an a hash literal is +symmetrical with respect to the opening brace and the hash +elements. + +If a hash's opening brace is on the same line as the first element +of the hash, then the closing brace should be on the same line as +the last element of the hash. + +If a hash's opening brace is on a separate line from the first +element of the hash, then the closing brace should be on the line +after the last element of the hash. + +### Example: + + # bad + { a: 'a', + b: 'b' + } + + # bad + { + a: 'a', + b: 'b' } + + # good + { a: 'a', + b: 'b' } + + #good + { + a: 'a', + b: 'b' + } \ No newline at end of file diff --git a/config/contents/style/multiline_if_then.md b/config/contents/style/multiline_if_then.md new file mode 100644 index 00000000..93483fb0 --- /dev/null +++ b/config/contents/style/multiline_if_then.md @@ -0,0 +1,12 @@ +Checks for uses of the `then` keyword in multi-line if statements. + +### Example: This is considered bad practice: + + if cond then + end + +### Example: If statements can contain `then` on the same line: + + if cond then a + elsif cond then b + end \ No newline at end of file diff --git a/config/contents/style/multiline_method_call_brace_layout.md b/config/contents/style/multiline_method_call_brace_layout.md new file mode 100644 index 00000000..295a6096 --- /dev/null +++ b/config/contents/style/multiline_method_call_brace_layout.md @@ -0,0 +1,33 @@ +This cop checks that the closing brace in a method call is +symmetrical with respect to the opening brace and the method +arguments. + +If a method call's opening brace is on the same line as the +first argument of the call, then the closing brace should be +on the same line as the last argument of the call. + +If a method call's opening brace is on a separate line from +the first argument of the call, then the closing brace should +be on the line after the last argument of the call. + +### Example: + + # 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/style/multiline_method_call_indentation.md b/config/contents/style/multiline_method_call_indentation.md new file mode 100644 index 00000000..6207f78d --- /dev/null +++ b/config/contents/style/multiline_method_call_indentation.md @@ -0,0 +1,26 @@ +This cop checks the indentation of the method name part in method calls +that span more than one line. + +### Example: + # bad + while a + .b + something + end + + # good, EnforcedStyle: aligned + while a + .b + something + end + + # good, EnforcedStyle: aligned + Thing.a + .b + .c + + # good, EnforcedStyle: indented + while a + .b + something + end \ No newline at end of file diff --git a/config/contents/style/multiline_method_definition_brace_layout.md b/config/contents/style/multiline_method_definition_brace_layout.md new file mode 100644 index 00000000..4c2f7d5c --- /dev/null +++ b/config/contents/style/multiline_method_definition_brace_layout.md @@ -0,0 +1,37 @@ +This cop checks that the closing brace in a method definition is +symmetrical with respect to the opening brace and the method +parameters. + +If a method definition's opening brace is on the same line as the +first parameter of the definition, then the closing brace should be +on the same line as the last parameter of the definition. + +If a method definition's opening brace is on a separate line from +the first parameter of the definition, then the closing brace should +be on the line after the last parameter of the definition. + +### Example: + + # 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/style/multiline_operation_indentation.md b/config/contents/style/multiline_operation_indentation.md new file mode 100644 index 00000000..a16df4ea --- /dev/null +++ b/config/contents/style/multiline_operation_indentation.md @@ -0,0 +1,9 @@ +This cop checks the indentation of the right hand side operand in +binary operations that span more than one line. + +### Example: + # bad + if a + + b + something + end \ No newline at end of file diff --git a/config/contents/style/mutable_constant.md b/config/contents/style/mutable_constant.md new file mode 100644 index 00000000..074bc292 --- /dev/null +++ b/config/contents/style/mutable_constant.md @@ -0,0 +1,9 @@ +This cop checks whether some constant value isn't a +mutable literal (e.g. array or hash). + +### Example: + # bad + CONST = [1, 2, 3] + + # good + CONST = [1, 2, 3].freeze \ No newline at end of file diff --git a/config/contents/style/nested_modifier.md b/config/contents/style/nested_modifier.md new file mode 100644 index 00000000..55aab044 --- /dev/null +++ b/config/contents/style/nested_modifier.md @@ -0,0 +1,10 @@ +This cop checks for nested use of if, unless, while and until in their +modifier form. + +### Example: + + # bad + something if a if b + + # good + something if b && a \ No newline at end of file diff --git a/config/contents/style/nested_parenthesized_calls.md b/config/contents/style/nested_parenthesized_calls.md new file mode 100644 index 00000000..1d7daff4 --- /dev/null +++ b/config/contents/style/nested_parenthesized_calls.md @@ -0,0 +1,9 @@ +This cop checks for unparenthesized method calls in the argument list +of a parenthesized method call. + +### Example: + # good + method1(method2(arg), method3(arg)) + + # bad + method1(method2 arg, method3, arg) \ No newline at end of file diff --git a/config/contents/style/next.md b/config/contents/style/next.md new file mode 100644 index 00000000..860287c1 --- /dev/null +++ b/config/contents/style/next.md @@ -0,0 +1,15 @@ +Use `next` to skip iteration instead of a condition at the end. + +### Example: + # bad + [1, 2].each do |a| + if a == 1 do + puts a + end + end + + # good + [1, 2].each do |a| + next unless a == 1 + puts a + end \ No newline at end of file diff --git a/config/contents/style/nil_comparison.md b/config/contents/style/nil_comparison.md new file mode 100644 index 00000000..f548a6e1 --- /dev/null +++ b/config/contents/style/nil_comparison.md @@ -0,0 +1,9 @@ +This cop checks for comparison of something with nil using ==. + +### Example: + + # bad + if x == nil + + # good + if x.nil? \ No newline at end of file diff --git a/config/contents/style/non_nil_check.md b/config/contents/style/non_nil_check.md new file mode 100644 index 00000000..9fc6f2db --- /dev/null +++ b/config/contents/style/non_nil_check.md @@ -0,0 +1,20 @@ +This cop checks for non-nil checks, which are usually redundant. + +### Example: + + # bad + if x != nil + + # good (when not allowing semantic changes) + # bad (when allowing semantic changes) + if !x.nil? + + # good (when allowing semantic changes) + if x + +Non-nil checks are allowed if they are the final nodes of predicate. + + # good + def signed_in? + !current_user.nil? + end \ No newline at end of file diff --git a/config/contents/style/option_hash.md b/config/contents/style/option_hash.md new file mode 100644 index 00000000..0fb3476e --- /dev/null +++ b/config/contents/style/option_hash.md @@ -0,0 +1,16 @@ +This cop checks for options hashes and discourages them if the +current Ruby version supports keyword arguments. + +### Example: + Instead of: + + def fry(options = {}) + temperature = options.fetch(:temperature, 300) + ... + end + + Prefer: + + def fry(temperature: 300) + ... + end \ No newline at end of file diff --git a/config/contents/style/optional_arguments.md b/config/contents/style/optional_arguments.md new file mode 100644 index 00000000..66c48bec --- /dev/null +++ b/config/contents/style/optional_arguments.md @@ -0,0 +1,14 @@ +This cop checks for optional arguments to methods +that do not come at the end of the argument list + +### Example: + # bad + def foo(a = 1, b, c) + end + + # good + def baz(a, b, c = 1) + end + + def foobar(a = 1, b = 2, c = 3) + end \ No newline at end of file diff --git a/config/contents/style/predicate_name.md b/config/contents/style/predicate_name.md new file mode 100644 index 00000000..658b850d --- /dev/null +++ b/config/contents/style/predicate_name.md @@ -0,0 +1,14 @@ +This cop makes sure that predicates are named properly. + +### Example: + # bad + def is_even?(value) ... + + # good + def even?(value) + + # bad + def has_value? ... + + # good + def value? ... \ No newline at end of file diff --git a/config/contents/style/redundant_begin.md b/config/contents/style/redundant_begin.md new file mode 100644 index 00000000..587c62bd --- /dev/null +++ b/config/contents/style/redundant_begin.md @@ -0,0 +1,21 @@ +This cop checks for redundant `begin` blocks. + +Currently it checks for code like this: + +### Example: + + def redundant + begin + ala + bala + rescue StandardError => e + something + end + end + + def preferred + ala + bala + rescue StandardError => e + something + end \ No newline at end of file diff --git a/config/contents/style/redundant_exception.md b/config/contents/style/redundant_exception.md new file mode 100644 index 00000000..05cdf462 --- /dev/null +++ b/config/contents/style/redundant_exception.md @@ -0,0 +1,7 @@ +This cop checks for RuntimeError as the argument of raise/fail. + +Currently it checks for code like this: + +### Example: + + raise RuntimeError, 'message' \ No newline at end of file diff --git a/config/contents/style/redundant_freeze.md b/config/contents/style/redundant_freeze.md new file mode 100644 index 00000000..e9b446c0 --- /dev/null +++ b/config/contents/style/redundant_freeze.md @@ -0,0 +1,8 @@ +This cop check for uses of Object#freeze on immutable objects. + +### Example: + # bad + CONST = 1.freeze + + # good + CONST = 1 \ No newline at end of file diff --git a/config/contents/style/redundant_parentheses.md b/config/contents/style/redundant_parentheses.md new file mode 100644 index 00000000..c70c234d --- /dev/null +++ b/config/contents/style/redundant_parentheses.md @@ -0,0 +1,9 @@ +This cop checks for redundant parentheses. + +### Example: + + # bad + (x) if ((y.z).nil?) + + # good + x if y.z.nil? diff --git a/config/contents/style/redundant_return.md b/config/contents/style/redundant_return.md new file mode 100644 index 00000000..44e0ac76 --- /dev/null +++ b/config/contents/style/redundant_return.md @@ -0,0 +1,17 @@ +This cop checks for redundant `return` expressions. + +### Example: + + def test + return something + end + + def test + one + two + three + 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 diff --git a/config/contents/style/redundant_self.md b/config/contents/style/redundant_self.md new file mode 100644 index 00000000..1af709cb --- /dev/null +++ b/config/contents/style/redundant_self.md @@ -0,0 +1,39 @@ +This cop checks for redundant uses of `self`. + +`self` is only needed when: + +* Sending a message to same object with zero arguments in + presence of a method name clash with an argument or a local + variable. + + Note, with using explicit self you can only send messages + with public or protected scope, you cannot send private + messages this way. + + Example: + + def bar + :baz + end + + def foo(bar) + self.bar # resolves name clash with argument + end + + def foo2 + bar = 1 + self.bar # resolves name clash with local variable + end + +* Calling an attribute writer to prevent an local variable assignment + + attr_writer :bar + + def foo + self.bar= 1 # Make sure above attr writer is called + end + +Special cases: + +We allow uses of `self` with operators because it would be awkward +otherwise. \ No newline at end of file diff --git a/config/contents/style/regexp_literal.md b/config/contents/style/regexp_literal.md new file mode 100644 index 00000000..8c049975 --- /dev/null +++ b/config/contents/style/regexp_literal.md @@ -0,0 +1,25 @@ +This cop enforces using // or %r around regular expressions. + +### Example: + # Good if EnforcedStyle is slashes or mixed, bad if percent_r. + snake_case = /^[\dA-Z_]+$/ + + # Good if EnforcedStyle is percent_r, bad if slashes or mixed. + snake_case = %r{^[\dA-Z_]+$} + + # Good if EnforcedStyle is slashes, bad if percent_r or mixed. + regex = / + foo + (bar) + (baz) + /x + + # Good if EnforcedStyle is percent_r or mixed, bad if slashes. + regex = %r{ + foo + (bar) + (baz) + }x + + # Bad unless AllowInnerSlashes is true. + x =~ /home\// \ No newline at end of file diff --git a/config/contents/style/rescue_ensure_alignment.md b/config/contents/style/rescue_ensure_alignment.md new file mode 100644 index 00000000..8f4b72e7 --- /dev/null +++ b/config/contents/style/rescue_ensure_alignment.md @@ -0,0 +1,18 @@ +This cop checks whether the rescue and ensure keywords are aligned +properly. + +### Example: + + # bad + begin + something + rescue + puts 'error' + end + + # good + begin + something + rescue + puts 'error' + end \ No newline at end of file diff --git a/config/contents/style/self_assignment.md b/config/contents/style/self_assignment.md new file mode 100644 index 00000000..393eaef9 --- /dev/null +++ b/config/contents/style/self_assignment.md @@ -0,0 +1,9 @@ +This cop enforces the use the shorthand for self-assignment. + +### Example: + + # bad + x = x + 1 + + # good + x += 1 \ No newline at end of file diff --git a/config/contents/style/space_after_method_name.md b/config/contents/style/space_after_method_name.md new file mode 100644 index 00000000..a2983bc9 --- /dev/null +++ b/config/contents/style/space_after_method_name.md @@ -0,0 +1,9 @@ +Checks for space between a method name and a left parenthesis in defs. + +### Example: + + # bad + def func (x) ... end + + # good + def func(x) ... end \ No newline at end of file diff --git a/config/contents/style/space_after_not.md b/config/contents/style/space_after_not.md new file mode 100644 index 00000000..384d3b6e --- /dev/null +++ b/config/contents/style/space_after_not.md @@ -0,0 +1,8 @@ +This cop checks for space after `!`. + +### Example: + # bad + ! something + + # good + !something \ No newline at end of file diff --git a/config/contents/style/space_around_block_parameters.md b/config/contents/style/space_around_block_parameters.md new file mode 100644 index 00000000..85f9f111 --- /dev/null +++ b/config/contents/style/space_around_block_parameters.md @@ -0,0 +1,9 @@ +Checks the spacing inside and after block parameters pipes. + +### Example: + + # bad + {}.each { | x, y |puts x } + + # good + {}.each { |x, y| puts x } \ No newline at end of file diff --git a/config/contents/style/space_around_keyword.md b/config/contents/style/space_around_keyword.md new file mode 100644 index 00000000..43d47eec --- /dev/null +++ b/config/contents/style/space_around_keyword.md @@ -0,0 +1,21 @@ +Checks the spacing around the keywords. + +### Example: + + # bad + something 'test'do|x| + end + + while(something) + end + + something = 123if test + + # good + something 'test' do |x| + end + + while (something) + end + + something = 123 if test \ No newline at end of file diff --git a/config/contents/style/space_before_first_arg.md b/config/contents/style/space_before_first_arg.md new file mode 100644 index 00000000..b6ab0e4c --- /dev/null +++ b/config/contents/style/space_before_first_arg.md @@ -0,0 +1,11 @@ +Checks that exactly one space is used between a method name and the +first argument for method calls without parentheses. + +Alternatively, extra spaces can be added to align the argument with +something on a preceding or following line, if the AllowForAlignment +config parameter is true. + +### Example: + # bad + something x + something y, z diff --git a/config/contents/style/space_inside_range_literal.md b/config/contents/style/space_inside_range_literal.md new file mode 100644 index 00000000..9d8e5d8c --- /dev/null +++ b/config/contents/style/space_inside_range_literal.md @@ -0,0 +1,14 @@ +Checks for spaces inside range literals. + +### Example: + # bad + 1 .. 3 + + # good + 1..3 + + # bad + 'a' .. 'z' + + # good + 'a'..'z' \ No newline at end of file diff --git a/config/contents/style/space_inside_string_interpolation.md b/config/contents/style/space_inside_string_interpolation.md new file mode 100644 index 00000000..67213f01 --- /dev/null +++ b/config/contents/style/space_inside_string_interpolation.md @@ -0,0 +1,8 @@ +This cop checks for whitespace within string interpolations. + +### Example: + # Good if EnforcedStyle is no_space, bad if space. + var = "This is the #{no_space} example" + + # Good if EnforceStyle is space, bad if no_space. + var = "This is the #{ space } example" \ No newline at end of file diff --git a/config/contents/style/struct_inheritance.md b/config/contents/style/struct_inheritance.md new file mode 100644 index 00000000..4eb00d93 --- /dev/null +++ b/config/contents/style/struct_inheritance.md @@ -0,0 +1,9 @@ +This cop checks for inheritance from Struct.new. + +### Example: + # bad + class Person < Struct.new(:first_name, :last_name) + end + + # good + Person = Struct.new(:first_name, :last_name) \ No newline at end of file diff --git a/config/contents/style/symbol_literal.md b/config/contents/style/symbol_literal.md new file mode 100644 index 00000000..5750b57a --- /dev/null +++ b/config/contents/style/symbol_literal.md @@ -0,0 +1,9 @@ +This cop checks symbol literal syntax. + +### Example: + + # bad + :"symbol" + + # good + :symbol \ No newline at end of file diff --git a/config/contents/style/symbol_proc.md b/config/contents/style/symbol_proc.md new file mode 100644 index 00000000..6bafa728 --- /dev/null +++ b/config/contents/style/symbol_proc.md @@ -0,0 +1,8 @@ +Use symbols as procs when possible. + +### Example: + # bad + something.map { |s| s.upcase } + + # good + something.map(&:upcase) \ No newline at end of file diff --git a/config/contents/style/trailing_comma_in_arguments.md b/config/contents/style/trailing_comma_in_arguments.md new file mode 100644 index 00000000..4872c146 --- /dev/null +++ b/config/contents/style/trailing_comma_in_arguments.md @@ -0,0 +1,23 @@ +This cop checks for trailing comma in argument lists. + +### Example: + # always bad + method(1, 2,) + + # good if EnforcedStyleForMultiline is consistent_comma + method( + 1, 2, + 3, + ) + + # good if EnforcedStyleForMultiline is comma or consistent_comma + method( + 1, + 2, + ) + + # good if EnforcedStyleForMultiline is no_comma + method( + 1, + 2 + ) \ No newline at end of file diff --git a/config/contents/style/trailing_comma_in_literal.md b/config/contents/style/trailing_comma_in_literal.md new file mode 100644 index 00000000..242fff2d --- /dev/null +++ b/config/contents/style/trailing_comma_in_literal.md @@ -0,0 +1,23 @@ +This cop checks for trailing comma in array and hash literals. + +### Example: + # always bad + a = [1, 2,] + + # good if EnforcedStyleForMultiline is consistent_comma + a = [ + 1, 2, + 3, + ] + + # good if EnforcedStyleForMultiline is comma or consistent_comma + a = [ + 1, + 2, + ] + + # good if EnforcedStyleForMultiline is no_comma + a = [ + 1, + 2 + ] \ No newline at end of file diff --git a/config/contents/style/trailing_underscore_variable.md b/config/contents/style/trailing_underscore_variable.md new file mode 100644 index 00000000..a8e4f831 --- /dev/null +++ b/config/contents/style/trailing_underscore_variable.md @@ -0,0 +1,14 @@ +This cop checks for extra underscores in variable assignment. + +### Example: + # bad + a, b, _ = foo() + a, b, _, = foo() + a, _, _ = foo() + a, _, _, = foo() + + #good + a, b, = foo() + a, = foo() + *a, b, _ = foo() => We need to know to not include 2 variables in a + a, *b, _ = foo() => The correction `a, *b, = foo()` is a syntax error \ No newline at end of file diff --git a/config/contents/style/unneeded_interpolation.md b/config/contents/style/unneeded_interpolation.md new file mode 100644 index 00000000..34d5078d --- /dev/null +++ b/config/contents/style/unneeded_interpolation.md @@ -0,0 +1,12 @@ +This cop checks for strings that are just an interpolated expression. + +### Example: + + # bad + "#{@var}" + + # good + @var.to_s + + # good if @var is already a String + @var \ No newline at end of file diff --git a/config/contents/style/zero_length_predicate.md b/config/contents/style/zero_length_predicate.md new file mode 100644 index 00000000..c939c5bc --- /dev/null +++ b/config/contents/style/zero_length_predicate.md @@ -0,0 +1,16 @@ +This cop checks for receiver.length == 0 predicates and the +negated versions receiver.length > 0 and receiver.length != 0. +These can be replaced with receiver.empty? and +!receiver.empty? respectively. + +### Example: + + # bad + [1, 2, 3].length == 0 + 0 == "foobar".length + hash.size > 0 + + # good + [1, 2, 3].empty? + "foobar".empty? + !hash.empty? \ No newline at end of file diff --git a/lib/tasks/docs.rake b/lib/tasks/docs.rake index 7b66c165..3bbb11a2 100644 --- a/lib/tasks/docs.rake +++ b/lib/tasks/docs.rake @@ -1,20 +1,25 @@ +require "rubocop" + namespace :docs do desc "Scrapes documentation from the rubocop gem" task :scrape do - TAG = "v0.34.2" COP_FOLDERS = %w[lint metrics performance rails style] %x{git clone https://github.com/bbatsov/rubocop.git rubocop-git} - %x{cd rubocop-git && git checkout tags/#{TAG}} + %x{cd rubocop-git && git checkout tags/v#{RuboCop::Version.version}} files = Dir.glob("./rubocop-git/lib/rubocop/cop/{#{COP_FOLDERS.join(',')}}/**.rb") documentation = files.each_with_object({}) do |file, hash| content = File.read(file) + content = content.gsub(/.*\n\s+(?=module RuboCop)/, "") + class_doc = content.match(/(\s+#.*)+/).to_s doc_lines = class_doc. gsub(/^\n/,""). gsub("@example", "### Example:"). + gsub("@good", "# good"). + gsub("@bad", "# bad"). split("\n"). map { |line| line.gsub(/\A\s+#\s?/, "") }. map { |line| line.gsub(/\A\s{2}/, " " * 4) }. diff --git a/spec/cc/engine/issue_spec.rb b/spec/cc/engine/issue_spec.rb index 84c0cb6d..5a1e295d 100644 --- a/spec/cc/engine/issue_spec.rb +++ b/spec/cc/engine/issue_spec.rb @@ -12,8 +12,8 @@ module CC::Engine location.last_column = 99 offense = OpenStruct.new - offense.cop_name = "Metrics/LineLength" - offense.message = "Line too long [100/80]" + offense.cop_name = "Metrics/CyclomaticComplexity" + offense.message = "Cyclomatic complexity for complex_method is too high [10/5]" offense.location = location Issue.new(offense, "app/models/user.rb") @@ -23,17 +23,17 @@ module CC::Engine attributes = JSON.parse(issue.to_json) expect(attributes["type"]).to eq("Issue") - expect(attributes["check_name"]).to eq("Rubocop/Metrics/LineLength") - expect(attributes["description"]).to eq("Line too long [100/80]") - expect(attributes["categories"]).to eq(["Style"]) - expect(attributes["remediation_points"]).to eq(50_000) + expect(attributes["check_name"]).to eq("Rubocop/Metrics/CyclomaticComplexity") + expect(attributes["description"]).to eq("Cyclomatic complexity for complex_method is too high [10/5]") + expect(attributes["categories"]).to eq(["Complexity"]) + expect(attributes["remediation_points"]).to eq(1_350_000) expect(attributes["location"]["path"]).to eq("app/models/user.rb") expect(attributes["location"]["positions"]["begin"]["line"]).to eq(10) expect(attributes["location"]["positions"]["end"]["line"]).to eq(10) expect(attributes["location"]["positions"]["begin"]["column"]).to eq(4) expect(attributes["location"]["positions"]["end"]["column"]).to eq(100) - expect(attributes["content"]["body"]).to include( - "This cop checks the length of lines in the source code." + expect(attributes["content"]["body"].squish).to include( + "This cop checks that the cyclomatic complexity of methods is not higher than the configured maximum." ) end end diff --git a/spec/cc/engine/rubocop_spec.rb b/spec/cc/engine/rubocop_spec.rb index 2b302579..26f24999 100644 --- a/spec/cc/engine/rubocop_spec.rb +++ b/spec/cc/engine/rubocop_spec.rb @@ -208,15 +208,6 @@ def method(a,b,c,d,e,f,g) expect(result["location"]).to eq(location) end - it "includes issue content when available" do - lines = " test\n" * 101 - create_source_file("klass.rb", "class Klass\n#{lines}end") - - output = run_engine - - expect(includes_content_for?(output, "Metrics/ClassLength")).to be true - end - it "uses only include_paths when they're passed in via the config hash" do okay_contents = <<-EORUBY #!/usr/bin/env ruby