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