rubocop 0.46.0 → 0.47.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +77 -2
- data/config/default.yml +151 -74
- data/config/disabled.yml +9 -0
- data/config/enabled.yml +49 -9
- data/lib/rubocop.rb +36 -8
- data/lib/rubocop/ast/builder.rb +59 -0
- data/lib/rubocop/ast/node.rb +607 -0
- data/lib/rubocop/ast/node/array_node.rb +45 -0
- data/lib/rubocop/ast/node/case_node.rb +63 -0
- data/lib/rubocop/ast/node/for_node.rb +53 -0
- data/lib/rubocop/ast/node/hash_node.rb +102 -0
- data/lib/rubocop/ast/node/if_node.rb +136 -0
- data/lib/rubocop/ast/node/keyword_splat_node.rb +45 -0
- data/lib/rubocop/ast/node/mixin/conditional_node.rb +45 -0
- data/lib/rubocop/ast/node/mixin/hash_element_node.rb +125 -0
- data/lib/rubocop/ast/node/mixin/modifier_node.rb +17 -0
- data/lib/rubocop/ast/node/pair_node.rb +64 -0
- data/lib/rubocop/ast/node/until_node.rb +43 -0
- data/lib/rubocop/ast/node/when_node.rb +61 -0
- data/lib/rubocop/ast/node/while_node.rb +43 -0
- data/lib/rubocop/ast/sexp.rb +16 -0
- data/lib/rubocop/{ast_node → ast}/traversal.rb +1 -1
- data/lib/rubocop/cli.rb +18 -14
- data/lib/rubocop/comment_config.rb +1 -3
- data/lib/rubocop/config.rb +93 -35
- data/lib/rubocop/config_loader.rb +1 -1
- data/lib/rubocop/cop/badge.rb +73 -0
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
- data/lib/rubocop/cop/bundler/ordered_gems.rb +43 -3
- data/lib/rubocop/cop/commissioner.rb +17 -6
- data/lib/rubocop/cop/cop.rb +25 -112
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +9 -4
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +7 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +18 -4
- data/lib/rubocop/cop/lint/block_alignment.rb +40 -9
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +14 -0
- data/lib/rubocop/cop/lint/condition_position.rb +14 -16
- data/lib/rubocop/cop/lint/debugger.rb +28 -0
- data/lib/rubocop/cop/lint/def_end_alignment.rb +21 -1
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +13 -1
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +26 -22
- data/lib/rubocop/cop/lint/duplicate_methods.rb +15 -1
- data/lib/rubocop/cop/lint/duplicated_key.rb +16 -8
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +9 -0
- data/lib/rubocop/cop/lint/else_layout.rb +26 -29
- data/lib/rubocop/cop/lint/empty_ensure.rb +38 -0
- data/lib/rubocop/cop/lint/empty_expression.rb +11 -1
- data/lib/rubocop/cop/lint/empty_interpolation.rb +8 -0
- data/lib/rubocop/cop/lint/empty_when.rb +14 -16
- data/lib/rubocop/cop/lint/end_alignment.rb +48 -28
- data/lib/rubocop/cop/lint/end_in_method.rb +23 -0
- data/lib/rubocop/cop/lint/ensure_return.rb +21 -0
- data/lib/rubocop/cop/lint/float_out_of_range.rb +5 -0
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +29 -4
- data/lib/rubocop/cop/lint/handle_exceptions.rb +40 -0
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +7 -2
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +11 -2
- data/lib/rubocop/cop/lint/invalid_character_literal.rb +3 -0
- data/lib/rubocop/cop/lint/literal_in_condition.rb +34 -36
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +8 -0
- data/lib/rubocop/cop/lint/loop.rb +36 -0
- data/lib/rubocop/cop/lint/multiple_compare.rb +46 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +22 -0
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +5 -0
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +8 -0
- data/lib/rubocop/cop/lint/percent_string_array.rb +27 -13
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +14 -4
- data/lib/rubocop/cop/lint/rand_one.rb +7 -3
- data/lib/rubocop/cop/lint/require_parentheses.rb +20 -19
- data/lib/rubocop/cop/lint/rescue_exception.rb +20 -0
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +66 -0
- data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -1
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +24 -0
- data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +8 -0
- data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +24 -0
- data/lib/rubocop/cop/lint/unified_integer.rb +5 -0
- data/lib/rubocop/cop/lint/unneeded_disable.rb +2 -2
- data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +5 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +17 -0
- data/lib/rubocop/cop/lint/unused_block_argument.rb +2 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +28 -1
- data/lib/rubocop/cop/lint/useless_assignment.rb +18 -0
- data/lib/rubocop/cop/lint/useless_comparison.rb +3 -1
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +16 -1
- data/lib/rubocop/cop/lint/useless_setter_call.rb +16 -4
- data/lib/rubocop/cop/lint/void.rb +52 -0
- data/lib/rubocop/cop/message_annotator.rb +102 -0
- data/lib/rubocop/cop/metrics/block_length.rb +6 -0
- data/lib/rubocop/cop/metrics/block_nesting.rb +17 -5
- data/lib/rubocop/cop/metrics/line_length.rb +11 -4
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -2
- data/lib/rubocop/cop/mixin/array_syntax.rb +2 -11
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +12 -5
- data/lib/rubocop/cop/mixin/configurable_formatting.rb +48 -0
- data/lib/rubocop/cop/mixin/configurable_max.rb +3 -3
- data/lib/rubocop/cop/mixin/configurable_naming.rb +5 -33
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +6 -47
- data/lib/rubocop/cop/mixin/documentation_comment.rb +7 -1
- data/lib/rubocop/cop/mixin/duplication.rb +46 -0
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +2 -2
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +14 -11
- data/lib/rubocop/cop/mixin/hash_alignment.rb +114 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -3
- data/lib/rubocop/cop/mixin/negative_conditional.rb +21 -7
- data/lib/rubocop/cop/mixin/on_method_def.rb +14 -0
- data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +1 -24
- data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -13
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +16 -0
- data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -3
- data/lib/rubocop/cop/offense.rb +1 -1
- data/lib/rubocop/cop/performance/case_when_splat.rb +56 -59
- data/lib/rubocop/cop/performance/detect.rb +2 -2
- data/lib/rubocop/cop/performance/flat_map.rb +3 -3
- data/lib/rubocop/cop/performance/redundant_merge.rb +3 -6
- data/lib/rubocop/cop/performance/regexp_match.rb +201 -0
- data/lib/rubocop/cop/rails/delegate.rb +2 -2
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +10 -19
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +12 -40
- data/lib/rubocop/cop/rails/file_path.rb +80 -0
- data/lib/rubocop/cop/rails/find_each.rb +5 -14
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +30 -24
- data/lib/rubocop/cop/rails/not_null_column.rb +23 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +217 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +4 -2
- data/lib/rubocop/cop/rails/skips_model_validations.rb +46 -0
- data/lib/rubocop/cop/rails/time_zone.rb +1 -1
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +7 -5
- data/lib/rubocop/cop/registry.rb +170 -0
- data/lib/rubocop/cop/{lint → security}/eval.rb +7 -1
- data/lib/rubocop/cop/security/marshal_load.rb +33 -0
- data/lib/rubocop/cop/security/yaml_load.rb +37 -0
- data/lib/rubocop/cop/style/align_hash.rb +138 -169
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +10 -15
- data/lib/rubocop/cop/style/case_indentation.rb +36 -27
- data/lib/rubocop/cop/style/conditional_assignment.rb +64 -47
- data/lib/rubocop/cop/style/each_with_object.rb +4 -1
- data/lib/rubocop/cop/style/else_alignment.rb +14 -20
- data/lib/rubocop/cop/style/empty_case_condition.rb +16 -25
- data/lib/rubocop/cop/style/empty_else.rb +20 -22
- data/lib/rubocop/cop/style/empty_literal.rb +4 -4
- data/lib/rubocop/cop/style/empty_method.rb +12 -6
- data/lib/rubocop/cop/style/encoding.rb +1 -1
- data/lib/rubocop/cop/style/file_name.rb +24 -4
- data/lib/rubocop/cop/style/first_method_argument_line_break.rb +1 -1
- data/lib/rubocop/cop/style/format_string.rb +17 -48
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +40 -11
- data/lib/rubocop/cop/style/guard_clause.rb +11 -17
- data/lib/rubocop/cop/style/hash_syntax.rb +24 -42
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +40 -28
- data/lib/rubocop/cop/style/if_inside_else.rb +6 -9
- data/lib/rubocop/cop/style/if_unless_modifier.rb +16 -25
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +3 -9
- data/lib/rubocop/cop/style/indent_array.rb +1 -1
- data/lib/rubocop/cop/style/indentation_width.rb +29 -60
- data/lib/rubocop/cop/style/infinite_loop.rb +21 -22
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +86 -0
- data/lib/rubocop/cop/style/{method_call_parentheses.rb → method_call_without_args_parentheses.rb} +8 -1
- data/lib/rubocop/cop/style/missing_else.rb +40 -14
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +5 -15
- data/lib/rubocop/cop/style/multiline_if_then.rb +14 -8
- data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +3 -3
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -5
- data/lib/rubocop/cop/style/mutable_constant.rb +3 -2
- data/lib/rubocop/cop/style/negated_if.rb +3 -19
- data/lib/rubocop/cop/style/negated_while.rb +2 -17
- data/lib/rubocop/cop/style/nested_modifier.rb +16 -43
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -5
- data/lib/rubocop/cop/style/next.rb +23 -21
- data/lib/rubocop/cop/style/non_nil_check.rb +2 -3
- data/lib/rubocop/cop/style/not.rb +1 -3
- data/lib/rubocop/cop/style/numeric_literals.rb +2 -2
- data/lib/rubocop/cop/style/one_line_conditional.rb +12 -22
- data/lib/rubocop/cop/style/option_hash.rb +4 -15
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -3
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -12
- data/lib/rubocop/cop/style/percent_q_literals.rb +15 -12
- data/lib/rubocop/cop/style/redundant_freeze.rb +3 -2
- data/lib/rubocop/cop/style/redundant_parentheses.rb +27 -4
- data/lib/rubocop/cop/style/redundant_return.rb +4 -8
- data/lib/rubocop/cop/style/safe_navigation.rb +13 -6
- data/lib/rubocop/cop/style/space_after_colon.rb +2 -4
- data/lib/rubocop/cop/style/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/style/space_around_operators.rb +15 -13
- data/lib/rubocop/cop/style/string_methods.rb +1 -3
- data/lib/rubocop/cop/style/symbol_array.rb +1 -5
- data/lib/rubocop/cop/style/ternary_parentheses.rb +5 -6
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +2 -5
- data/lib/rubocop/cop/style/trailing_comma_in_literal.rb +1 -1
- data/lib/rubocop/cop/style/unless_else.rb +1 -5
- data/lib/rubocop/cop/style/when_then.rb +4 -2
- data/lib/rubocop/cop/style/while_until_do.rb +9 -13
- data/lib/rubocop/cop/style/while_until_modifier.rb +12 -11
- data/lib/rubocop/cop/style/word_array.rb +5 -9
- data/lib/rubocop/cop/team.rb +16 -15
- data/lib/rubocop/cop/util.rb +13 -3
- data/lib/rubocop/formatter/clang_style_formatter.rb +2 -2
- data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
- data/lib/rubocop/magic_comment.rb +196 -0
- data/lib/rubocop/options.rb +5 -4
- data/lib/rubocop/processed_source.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +9 -0
- data/lib/rubocop/rspec/shared_examples.rb +1 -1
- data/lib/rubocop/runner.rb +7 -2
- data/lib/rubocop/version.rb +1 -1
- metadata +41 -14
- data/lib/rubocop/ast_node.rb +0 -624
- data/lib/rubocop/ast_node/builder.rb +0 -30
- data/lib/rubocop/ast_node/sexp.rb +0 -13
- data/lib/rubocop/cop/mixin/hash_node.rb +0 -14
- data/lib/rubocop/cop/mixin/if_node.rb +0 -42
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# A node extension for `array` nodes. This will be used in place of a plain
|
6
|
+
# node when the builder constructs the AST, making its methods available
|
7
|
+
# to all `array` nodes within RuboCop.
|
8
|
+
class ArrayNode < Node
|
9
|
+
PERCENT_LITERAL_TYPES = {
|
10
|
+
string: /^%[wW]/,
|
11
|
+
symbol: /^%[iI]/
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
# Returns an array of all value nodes in the `array` literal.
|
15
|
+
#
|
16
|
+
# @return [Array<Node>] an array of value nodes
|
17
|
+
def values
|
18
|
+
each_child_node.to_a
|
19
|
+
end
|
20
|
+
|
21
|
+
# Checks whether the `array` literal is delimited by square brackets.
|
22
|
+
#
|
23
|
+
# @return [Boolean] whether the array is enclosed in square brackets
|
24
|
+
def square_brackets?
|
25
|
+
loc.begin && loc.begin.is?('[')
|
26
|
+
end
|
27
|
+
|
28
|
+
# Checks whether the `array` literal is delimited by percent brackets.
|
29
|
+
#
|
30
|
+
# @overload percent_literal?
|
31
|
+
# Check for any percent literal.
|
32
|
+
# @overload percent_literal?(type)
|
33
|
+
# Check for percent literaly of type `type`.
|
34
|
+
# @param type [Symbol] an optional percent literal type
|
35
|
+
# @return [Boolean] whether the array is enclosed in percent brackets
|
36
|
+
def percent_literal?(type = nil)
|
37
|
+
if type
|
38
|
+
loc.begin && loc.begin.source =~ PERCENT_LITERAL_TYPES[type]
|
39
|
+
else
|
40
|
+
loc.begin && loc.begin.source.start_with?('%')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# A node extension for `case` nodes. This will be used in place of a plain
|
6
|
+
# node when the builder constructs the AST, making its methods available
|
7
|
+
# to all `case` nodes within RuboCop.
|
8
|
+
class CaseNode < Node
|
9
|
+
include ConditionalNode
|
10
|
+
|
11
|
+
# Returns the keyword of the `case` statement as a string.
|
12
|
+
#
|
13
|
+
# @return [String] the keyword of the `case` statement
|
14
|
+
def keyword
|
15
|
+
'case'
|
16
|
+
end
|
17
|
+
|
18
|
+
# Calls the given block for each `when` node in the `case` statement.
|
19
|
+
# If no block is given, an `Enumerator` is returned.
|
20
|
+
#
|
21
|
+
# @return [self] if a block is given
|
22
|
+
# @return [Enumerator] if no block is given
|
23
|
+
def each_when
|
24
|
+
return when_branches.to_enum(__method__) unless block_given?
|
25
|
+
|
26
|
+
when_branches.each do |condition|
|
27
|
+
yield condition
|
28
|
+
end
|
29
|
+
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns an array of all the when branches in the `case` statement.
|
34
|
+
#
|
35
|
+
# @return [Array<WhenNode>] an array of `when` nodes
|
36
|
+
def when_branches
|
37
|
+
node_parts[1...-1]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the else branch of the `case` statement, if any.
|
41
|
+
#
|
42
|
+
# @return [Node] the else branch node of the `case` statement
|
43
|
+
def else_branch
|
44
|
+
node_parts[-1]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Checks whether this case statement has an `else` branch.
|
48
|
+
#
|
49
|
+
# @return [Boolean] whether the `case` statement has an `else` branch
|
50
|
+
def else?
|
51
|
+
loc.else
|
52
|
+
end
|
53
|
+
|
54
|
+
# Custom destructuring method. This can be used to normalize
|
55
|
+
# destructuring for different variations of the node.
|
56
|
+
#
|
57
|
+
# @return [Array<Node>] the different parts of the `case` statement
|
58
|
+
def node_parts
|
59
|
+
[*self]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# A node extension for `for` nodes. This will be used in place of a plain
|
6
|
+
# node when the builder constructs the AST, making its methods available
|
7
|
+
# to all `for` nodes within RuboCop.
|
8
|
+
class ForNode < Node
|
9
|
+
# Returns the keyword of the `for` statement as a string.
|
10
|
+
#
|
11
|
+
# @return [String] the keyword of the `until` statement
|
12
|
+
def keyword
|
13
|
+
'for'
|
14
|
+
end
|
15
|
+
|
16
|
+
# Checks whether the `for` node has a `do` keyword.
|
17
|
+
#
|
18
|
+
# @return [Boolean] whether the `for` node has a `do` keyword
|
19
|
+
def do?
|
20
|
+
loc.begin && loc.begin.is?('do')
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the iteration variable of the `for` loop.
|
24
|
+
#
|
25
|
+
# @return [Node] The iteration variable of the `for` loop
|
26
|
+
def variable
|
27
|
+
node_parts[0]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the collection the `for` loop is iterating over.
|
31
|
+
#
|
32
|
+
# @return [Node] The collection the `for` loop is iterating over
|
33
|
+
def collection
|
34
|
+
node_parts[1]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the body of the `for` loop.
|
38
|
+
#
|
39
|
+
# @return [Node, nil] The body of the `for` loop.
|
40
|
+
def body
|
41
|
+
node_parts[2]
|
42
|
+
end
|
43
|
+
|
44
|
+
# Custom destructuring method. This can be used to normalize
|
45
|
+
# destructuring for different variations of the node.
|
46
|
+
#
|
47
|
+
# @return [Array<Node>] the different parts of the `until` statement
|
48
|
+
def node_parts
|
49
|
+
[*self]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# A node extension for `hash` nodes. This will be used in place of a plain
|
6
|
+
# node when the builder constructs the AST, making its methods available
|
7
|
+
# to all `hash` nodes within RuboCop.
|
8
|
+
class HashNode < Node
|
9
|
+
# Returns an array of all the key value pairs in the `hash` literal.
|
10
|
+
#
|
11
|
+
# @return [Array<PairNode>] an array of `pair` nodes
|
12
|
+
def pairs
|
13
|
+
each_pair.to_a
|
14
|
+
end
|
15
|
+
|
16
|
+
# Calls the given block for each `pair` node in the `hash` literal.
|
17
|
+
# If no block is given, an `Enumerator` is returned.
|
18
|
+
#
|
19
|
+
# @return [self] if a block is given
|
20
|
+
# @return [Enumerator] if no block is given
|
21
|
+
def each_pair
|
22
|
+
return each_child_node(:pair).to_enum unless block_given?
|
23
|
+
|
24
|
+
each_child_node(:pair) do |pair|
|
25
|
+
yield(*pair)
|
26
|
+
end
|
27
|
+
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns an array of all the keys in the `hash` literal.
|
32
|
+
#
|
33
|
+
# @return [Node] an array of keys in the `hash` literal
|
34
|
+
def keys
|
35
|
+
each_key.to_a
|
36
|
+
end
|
37
|
+
|
38
|
+
# Calls the given block for each `key` node in the `hash` literal.
|
39
|
+
# If no block is given, an `Enumerator` is returned.
|
40
|
+
#
|
41
|
+
# @return [self] if a block is given
|
42
|
+
# @return [Enumerator] if no block is given
|
43
|
+
def each_key
|
44
|
+
return pairs.map(&:key).to_enum unless block_given?
|
45
|
+
|
46
|
+
pairs.map(&:key).each do |key|
|
47
|
+
yield key
|
48
|
+
end
|
49
|
+
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns an array of all the values in the `hash` literal.
|
54
|
+
#
|
55
|
+
# @return [Node] an array of values in the `hash` literal
|
56
|
+
def values
|
57
|
+
each_pair.map(&:value)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Calls the given block for each `value` node in the `hash` literal.
|
61
|
+
# If no block is given, an `Enumerator` is returned.
|
62
|
+
#
|
63
|
+
# @return [self] if a block is given
|
64
|
+
# @return [Enumerator] if no block is given
|
65
|
+
def each_value
|
66
|
+
return pairs.map(&:value).to_enum unless block_given?
|
67
|
+
|
68
|
+
pairs.map(&:value).each do |value|
|
69
|
+
yield value
|
70
|
+
end
|
71
|
+
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
# Checks whether any of the key value pairs in the `hash` literal are on
|
76
|
+
# the same line.
|
77
|
+
#
|
78
|
+
# @note A multiline `pair` is considered to be on the same line if it
|
79
|
+
# shares any of its lines with another `pair`
|
80
|
+
#
|
81
|
+
# @return [Boolean] whether any `pair` nodes are on the same line
|
82
|
+
def pairs_on_same_line?
|
83
|
+
pairs.each_cons(2).any? { |first, second| first.same_line?(second) }
|
84
|
+
end
|
85
|
+
|
86
|
+
# Checks whether this `hash` uses a mix of hash rocket and colon
|
87
|
+
# delimiters for its pairs.
|
88
|
+
#
|
89
|
+
# @return [Boolean] whether the `hash` uses mixed delimiters
|
90
|
+
def mixed_delimiters?
|
91
|
+
pairs.map(&:delimiter).uniq.size > 1
|
92
|
+
end
|
93
|
+
|
94
|
+
# Checks whether the `hash` literal is delimited by curly braces.
|
95
|
+
#
|
96
|
+
# @return [Boolean] whether the `hash` literal is enclosed in braces
|
97
|
+
def braces?
|
98
|
+
loc.end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# A node extension for `if` nodes. This will be used in place of a plain
|
6
|
+
# node when the builder constructs the AST, making its methods available
|
7
|
+
# to all `if` nodes within RuboCop.
|
8
|
+
class IfNode < Node
|
9
|
+
include ConditionalNode
|
10
|
+
include ModifierNode
|
11
|
+
|
12
|
+
# Checks whether this node is an `if` statement. (This is not true of
|
13
|
+
# ternary operators and `unless` statements.)
|
14
|
+
#
|
15
|
+
# @return [Boolean] whether the node is an `if` statement
|
16
|
+
def if?
|
17
|
+
keyword == 'if'
|
18
|
+
end
|
19
|
+
|
20
|
+
# Checks whether this node is an `unless` statement. (This is not true
|
21
|
+
# of ternary operators and `if` statements.)
|
22
|
+
#
|
23
|
+
# @return [Boolean] whether the node is an `unless` statement
|
24
|
+
def unless?
|
25
|
+
keyword == 'unless'
|
26
|
+
end
|
27
|
+
|
28
|
+
# Checks whether the `if` is an `elsif`. Parser handles these by nesting
|
29
|
+
# `if` nodes in the `else` branch.
|
30
|
+
#
|
31
|
+
# @return [Boolean] whether the node is an `elsif`
|
32
|
+
def elsif?
|
33
|
+
keyword == 'elsif'
|
34
|
+
end
|
35
|
+
|
36
|
+
# Checks whether the `if` node has an `else` clause.
|
37
|
+
#
|
38
|
+
# @note This returns `true` for nodes containing an `elsif` clause.
|
39
|
+
# This is legacy behaviour, and many cops rely on it.
|
40
|
+
#
|
41
|
+
# @return [Boolean] whether the node has an `else` clause
|
42
|
+
def else?
|
43
|
+
loc.respond_to?(:else) && loc.else
|
44
|
+
end
|
45
|
+
|
46
|
+
# Checks whether the `if` node is a ternary operator.
|
47
|
+
#
|
48
|
+
# @return [Boolean] whether the `if` node is a ternary operator
|
49
|
+
def ternary?
|
50
|
+
loc.respond_to?(:question)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns the keyword of the `if` statement as a string. Returns an empty
|
54
|
+
# string for ternary operators.
|
55
|
+
#
|
56
|
+
# @return [String] the keyword of the `if` statement
|
57
|
+
def keyword
|
58
|
+
ternary? ? '' : loc.keyword.source
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns the inverse keyword of the `if` node as a string. Returns `if`
|
62
|
+
# for `unless` nodes and vice versa. Returns an empty string for ternary
|
63
|
+
# operators.
|
64
|
+
#
|
65
|
+
# @return [String] the inverse keyword of the `if` statement
|
66
|
+
def inverse_keyword
|
67
|
+
if keyword == 'if'
|
68
|
+
'unless'
|
69
|
+
elsif keyword == 'unless'
|
70
|
+
'if'
|
71
|
+
else
|
72
|
+
''
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Checks whether the `if` node is in a modifier form, i.e. a condition
|
77
|
+
# trailing behind an expression. Only `if` and `unless` nodes without
|
78
|
+
# other branches can be modifiers.
|
79
|
+
#
|
80
|
+
# @return [Boolean] whether the `if` node is a modifier
|
81
|
+
def modifier_form?
|
82
|
+
(if? || unless?) && super
|
83
|
+
end
|
84
|
+
|
85
|
+
# Chackes whether the `if` node has nested `if` nodes in any of its
|
86
|
+
# branches.
|
87
|
+
#
|
88
|
+
# @note This is a shallow search.
|
89
|
+
#
|
90
|
+
# @return [Boolean] whether the `if` node contains nested conditionals
|
91
|
+
def nested_conditional?
|
92
|
+
node_parts[1..2].compact.each do |branch|
|
93
|
+
branch.each_node(:if) do |nested|
|
94
|
+
return true unless nested.elsif?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
false
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns the branch of the `if` node that gets evaluated when its
|
102
|
+
# condition is truthy.
|
103
|
+
#
|
104
|
+
# @note This is normalized for `unless` nodes.
|
105
|
+
#
|
106
|
+
# @return [Node] the truthy branch node of the `if` node
|
107
|
+
def if_branch
|
108
|
+
node_parts[1]
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns the branch of the `if` node that gets evaluated when its
|
112
|
+
# condition is falsey.
|
113
|
+
#
|
114
|
+
# @note This is normalized for `unless` nodes.
|
115
|
+
#
|
116
|
+
# @return [Node] the falsey branch node of the `if` node
|
117
|
+
def else_branch
|
118
|
+
node_parts[2]
|
119
|
+
end
|
120
|
+
|
121
|
+
# Custom destructuring method. This is used to normalize the branches
|
122
|
+
# for `if` and `unless` nodes, to aid comparisons and conversions.
|
123
|
+
#
|
124
|
+
# @return [Array<Node>] the different parts of the `if` statement
|
125
|
+
def node_parts
|
126
|
+
if unless?
|
127
|
+
condition, false_branch, true_branch = *self
|
128
|
+
else
|
129
|
+
condition, true_branch, false_branch = *self
|
130
|
+
end
|
131
|
+
|
132
|
+
[condition, true_branch, false_branch]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# A node extension for `kwsplat` nodes. This will be used in place of a
|
6
|
+
# plain node when the builder constructs the AST, making its methods
|
7
|
+
# available to all `kwsplat` nodes within RuboCop.
|
8
|
+
class KeywordSplatNode < Node
|
9
|
+
include HashElementNode
|
10
|
+
|
11
|
+
DOUBLE_SPLAT = '**'.freeze
|
12
|
+
|
13
|
+
# This is used for duck typing with `pair` nodes which also appear as
|
14
|
+
# `hash` elements.
|
15
|
+
#
|
16
|
+
# @return [false]
|
17
|
+
def hash_rocket?
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
# This is used for duck typing with `pair` nodes which also appear as
|
22
|
+
# `hash` elements.
|
23
|
+
#
|
24
|
+
# @return [false]
|
25
|
+
def colon?
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the operator for the `kwsplat` as a string.
|
30
|
+
#
|
31
|
+
# @return [String] the double splat operator
|
32
|
+
def operator
|
33
|
+
DOUBLE_SPLAT
|
34
|
+
end
|
35
|
+
|
36
|
+
# Custom destructuring method. This is used to normalize the branches
|
37
|
+
# for `pair` and `kwsplat` nodes, to add duck typing to `hash` elements.
|
38
|
+
#
|
39
|
+
# @return [Array<KeywordSplatNode>] the different parts of the `kwsplat`
|
40
|
+
def node_parts
|
41
|
+
[self, self]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|