rubocop-ast 1.33.0 → 1.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 01f8352e57bd480b219c3219e60a2e7750e03dfbec0e34c0c0235139d11c0870
4
- data.tar.gz: 390a70bd777f6525138ab82faf2242d90ee1c1ace80dc7219e420e4d8780e296
3
+ metadata.gz: 71290c5f117f13043b681f7ce182d115284b84675bbfc0bf35448152ebfb42bd
4
+ data.tar.gz: 3c13a0e8e089409da5dd353bfea60c3981f56dac094f7a650690f3862bdf3e36
5
5
  SHA512:
6
- metadata.gz: b949d204d6c94ac8b4a3ac2546eb25f21a317cb74ea2a8b668c06e504a8b37775c4b6b3257ee59a15231cfbcc97d5c20500680d244e722173dffd4dd80620baf
7
- data.tar.gz: b0cbd03ab6d36c40a450e1faccd8eeecdb1b8edfcb0d8dae0e3e3c0adb5050a88967b8fdccb1a553e2f5e63fcfadebb5327e54c25d941df02633071d21a3b449
6
+ metadata.gz: '08c425d33229f9116b91905ef14ea762ad2d17603ae581795d3101526a51ee6a4c8e1ab2e508f2355b688e4143f668e71767f8283934ee3b27f045315add0a28'
7
+ data.tar.gz: 58173b8980810073f670c9087905923661d8a3fe0a43c17b354388ee07728611a6c5d1a690a2813184a6d4286c29c090d11d4f28de001ae395bfb774c53720bc
@@ -63,6 +63,7 @@ module RuboCop
63
63
  irange: RangeNode,
64
64
  erange: RangeNode,
65
65
  kwargs: HashNode,
66
+ kwbegin: KeywordBeginNode,
66
67
  kwsplat: KeywordSplatNode,
67
68
  lambda: LambdaNode,
68
69
  masgn: MasgnNode,
@@ -34,7 +34,7 @@ module RuboCop
34
34
  #
35
35
  # @return [Boolean] whether the array is enclosed in square brackets
36
36
  def square_brackets?
37
- loc.begin&.is?('[')
37
+ loc_is?(:begin, '[')
38
38
  end
39
39
 
40
40
  # Checks whether the `array` literal is delimited by percent brackets.
@@ -12,6 +12,7 @@ module RuboCop
12
12
  def name
13
13
  node_parts[0]
14
14
  end
15
+ alias lhs name
15
16
 
16
17
  # The expression being assigned to the variable.
17
18
  #
@@ -19,6 +20,7 @@ module RuboCop
19
20
  def expression
20
21
  node_parts[1]
21
22
  end
23
+ alias rhs expression
22
24
  end
23
25
  end
24
26
  end
@@ -9,6 +9,7 @@ module RuboCop
9
9
  include ConstantNode
10
10
 
11
11
  alias name short_name
12
+ alias lhs short_name
12
13
 
13
14
  # The expression being assigned to the variable.
14
15
  #
@@ -16,6 +17,7 @@ module RuboCop
16
17
  def expression
17
18
  node_parts[2]
18
19
  end
20
+ alias rhs expression
19
21
  end
20
22
  end
21
23
  end
@@ -9,10 +9,25 @@ module RuboCop
9
9
  # Returns the body of the `ensure` clause.
10
10
  #
11
11
  # @return [Node, nil] The body of the `ensure`.
12
+ # @deprecated Use `EnsureNode#branch`
12
13
  def body
14
+ branch
15
+ end
16
+
17
+ # Returns an the ensure branch in the exception handling statement.
18
+ #
19
+ # @return [Node, nil] the body of the ensure branch.
20
+ def branch
13
21
  node_parts[1]
14
22
  end
15
23
 
24
+ # Returns the `rescue` node of the `ensure`, if present.
25
+ #
26
+ # @return [Node, nil] The `rescue` node.
27
+ def rescue_node
28
+ node_parts[0] if node_parts[0].rescue_type?
29
+ end
30
+
16
31
  # Checks whether this node body is a void context.
17
32
  # Always `true` for `ensure`.
18
33
  #
@@ -17,7 +17,7 @@ module RuboCop
17
17
  #
18
18
  # @return [Boolean] whether the `for` node has a `do` keyword
19
19
  def do?
20
- loc.begin&.is?('do')
20
+ loc_is?(:begin, 'do')
21
21
  end
22
22
 
23
23
  # Checks whether this node body is a void context.
@@ -115,7 +115,7 @@ module RuboCop
115
115
  #
116
116
  # @return [Boolean] whether the `hash` literal is enclosed in braces
117
117
  def braces?
118
- loc.end&.is?('}')
118
+ loc_is?(:end, '}')
119
119
  end
120
120
  end
121
121
  end
@@ -25,6 +25,13 @@ module RuboCop
25
25
  keyword == 'unless'
26
26
  end
27
27
 
28
+ # Checks whether the `if` node has an `then` clause.
29
+ #
30
+ # @return [Boolean] whether the node has an `then` clause
31
+ def then?
32
+ loc_is?(:begin, 'then')
33
+ end
34
+
28
35
  # Checks whether the `if` is an `elsif`. Parser handles these by nesting
29
36
  # `if` nodes in the `else` branch.
30
37
  #
@@ -24,7 +24,7 @@ module RuboCop
24
24
  #
25
25
  # @return [Boolean] whether the `in` node has a `then` keyword
26
26
  def then?
27
- loc.begin&.is?('then')
27
+ loc_is?(:begin, 'then')
28
28
  end
29
29
 
30
30
  # Returns the body of the `in` node.
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # A node extension for `kwbegin` 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 `kwbegin` nodes within RuboCop.
8
+ class KeywordBeginNode < Node
9
+ # Returns the body of the `kwbegin` block. Returns `self` if the `kwbegin` contains
10
+ # multiple nodes.
11
+ #
12
+ # @return [Node, nil] The body of the `kwbegin`.
13
+ def body
14
+ return unless node_parts.any?
15
+
16
+ if rescue_node
17
+ rescue_node.body
18
+ elsif ensure_node
19
+ ensure_node.node_parts[0]
20
+ elsif node_parts.one?
21
+ node_parts[0]
22
+ else
23
+ self
24
+ end
25
+ end
26
+
27
+ # Returns the `rescue` node of the `kwbegin` block, if one is present.
28
+ #
29
+ # @return [Node, nil] The `rescue` node within `kwbegin`.
30
+ def ensure_node
31
+ node_parts[0] if node_parts[0]&.ensure_type?
32
+ end
33
+
34
+ # Returns the `rescue` node of the `kwbegin` block, if one is present.
35
+ #
36
+ # @return [Node, nil] The `rescue` node within `kwbegin`.
37
+ def rescue_node
38
+ return ensure_node&.rescue_node if ensure_node&.rescue_node
39
+
40
+ node_parts[0] if node_parts[0]&.rescue_type?
41
+ end
42
+ end
43
+ end
44
+ end
@@ -117,7 +117,7 @@ module RuboCop
117
117
  #
118
118
  # @return [Boolean] whether the method was called with a connecting dot
119
119
  def dot?
120
- loc.respond_to?(:dot) && loc.dot&.is?('.')
120
+ loc_is?(:dot, '.')
121
121
  end
122
122
 
123
123
  # Checks whether the dispatched method uses a double colon to connect the
@@ -125,7 +125,7 @@ module RuboCop
125
125
  #
126
126
  # @return [Boolean] whether the method was called with a connecting dot
127
127
  def double_colon?
128
- loc.respond_to?(:dot) && loc.dot&.is?('::')
128
+ loc_is?(:dot, '::')
129
129
  end
130
130
 
131
131
  # Checks whether the dispatched method uses a safe navigation operator to
@@ -133,7 +133,7 @@ module RuboCop
133
133
  #
134
134
  # @return [Boolean] whether the method was called with a connecting dot
135
135
  def safe_navigation?
136
- loc.respond_to?(:dot) && loc.dot&.is?('&.')
136
+ loc_is?(:dot, '&.')
137
137
  end
138
138
 
139
139
  # Checks whether the *explicit* receiver of this method dispatch is
@@ -281,7 +281,7 @@ module RuboCop
281
281
 
282
282
  # @!method non_bare_access_modifier_declaration?(node = self)
283
283
  def_node_matcher :non_bare_access_modifier_declaration?, <<~PATTERN
284
- (send nil? {:public :protected :private :module_function} _)
284
+ (send nil? {:public :protected :private :module_function} _+)
285
285
  PATTERN
286
286
  end
287
287
  end
@@ -13,7 +13,7 @@ module RuboCop
13
13
  # @return [Boolean] whether this node's arguments are
14
14
  # wrapped in parentheses
15
15
  def parenthesized?
16
- loc.end&.is?(')')
16
+ loc_is?(:end, ')')
17
17
  end
18
18
 
19
19
  # A shorthand for getting the first argument of the node.
@@ -8,13 +8,15 @@ module RuboCop
8
8
  class MlhsNode < Node
9
9
  # Returns all the assignment nodes on the left hand side (LHS) of a multiple assignment.
10
10
  # These are generally assignment nodes (`lvasgn`, `ivasgn`, `cvasgn`, `gvasgn`, `casgn`)
11
- # but can also be `send` nodes in case of `foo.bar, ... =` or `foo[:bar], ... =`.
11
+ # but can also be `send` nodes in case of `foo.bar, ... =` or `foo[:bar], ... =`,
12
+ # or a `splat` node for `*, ... =`.
12
13
  #
13
14
  # @return [Array<Node>] the assignment nodes of the multiple assignment LHS
14
15
  def assignments
15
16
  child_nodes.flat_map do |node|
16
17
  if node.splat_type?
17
- node.child_nodes.first
18
+ # Anonymous splats have no children
19
+ node.child_nodes.first || node
18
20
  elsif node.mlhs_type?
19
21
  node.assignments
20
22
  else
@@ -10,12 +10,13 @@ module RuboCop
10
10
  def assignment_node
11
11
  node_parts[0]
12
12
  end
13
+ alias lhs assignment_node
13
14
 
14
15
  # The name of the variable being assigned as a symbol.
15
16
  #
16
17
  # @return [Symbol] the name of the variable being assigned
17
18
  def name
18
- assignment_node.name
19
+ assignment_node.call_type? ? assignment_node.method_name : assignment_node.name
19
20
  end
20
21
 
21
22
  # The operator being used for assignment as a symbol.
@@ -31,6 +32,7 @@ module RuboCop
31
32
  def expression
32
33
  node_parts.last
33
34
  end
35
+ alias rhs expression
34
36
  end
35
37
  end
36
38
  end
@@ -8,13 +8,49 @@ module RuboCop
8
8
  class StrNode < Node
9
9
  include BasicLiteralNode
10
10
 
11
+ PERCENT_LITERAL_TYPES = {
12
+ :% => /\A%(?=[^a-zA-Z])/,
13
+ :q => /\A%q/,
14
+ :Q => /\A%Q/
15
+ }.freeze
16
+
17
+ def single_quoted?
18
+ loc_is?(:begin, "'")
19
+ end
20
+
21
+ def double_quoted?
22
+ loc_is?(:begin, '"')
23
+ end
24
+
11
25
  def character_literal?
12
- loc.respond_to?(:begin) && loc.begin&.is?('?')
26
+ loc_is?(:begin, '?')
13
27
  end
14
28
 
15
29
  def heredoc?
16
30
  loc.is_a?(Parser::Source::Map::Heredoc)
17
31
  end
32
+
33
+ # Checks whether the string literal is delimited by percent brackets.
34
+ #
35
+ # @overload percent_literal?
36
+ # Check for any string percent literal.
37
+ #
38
+ # @overload percent_literal?(type)
39
+ # Check for a string percent literal of type `type`.
40
+ #
41
+ # @param type [Symbol] an optional percent literal type
42
+ #
43
+ # @return [Boolean] whether the string is enclosed in percent brackets
44
+ def percent_literal?(type = nil)
45
+ opening_delimiter = loc.begin if loc.respond_to?(:begin)
46
+ return false unless opening_delimiter
47
+
48
+ if type
49
+ opening_delimiter.source.match?(PERCENT_LITERAL_TYPES.fetch(type))
50
+ else
51
+ opening_delimiter.source.start_with?('%')
52
+ end
53
+ end
18
54
  end
19
55
  end
20
56
  end
@@ -28,7 +28,7 @@ module RuboCop
28
28
  #
29
29
  # @return [Boolean] whether the `until` node has a `do` keyword
30
30
  def do?
31
- loc.begin&.is?('do')
31
+ loc_is?(:begin, 'do')
32
32
  end
33
33
  end
34
34
  end
@@ -33,7 +33,7 @@ module RuboCop
33
33
  #
34
34
  # @return [Boolean] whether the `when` node has a `then` keyword
35
35
  def then?
36
- loc.begin&.is?('then')
36
+ loc_is?(:begin, 'then')
37
37
  end
38
38
 
39
39
  # Returns the body of the `when` node.
@@ -28,7 +28,7 @@ module RuboCop
28
28
  #
29
29
  # @return [Boolean] whether the `until` node has a `do` keyword
30
30
  def do?
31
- loc.begin&.is?('do')
31
+ loc_is?(:begin, 'do')
32
32
  end
33
33
  end
34
34
  end
@@ -88,6 +88,34 @@ module RuboCop
88
88
  EMPTY_PROPERTIES = {}.freeze
89
89
  private_constant :EMPTY_CHILDREN, :EMPTY_PROPERTIES
90
90
 
91
+ # @api private
92
+ GROUP_FOR_TYPE = {
93
+ arg: :argument,
94
+ optarg: :argument,
95
+ restarg: :argument,
96
+ kwarg: :argument,
97
+ kwoptarg: :argument,
98
+ kwrestarg: :argument,
99
+ blockarg: :argument,
100
+ forward_arg: :argument,
101
+ shardowarg: :argument,
102
+
103
+ true: :boolean,
104
+ false: :boolean,
105
+
106
+ int: :numeric,
107
+ float: :numeric,
108
+ rational: :numeric,
109
+ complex: :numeric,
110
+
111
+ irange: :range,
112
+ erange: :range,
113
+
114
+ send: :call,
115
+ csend: :call
116
+ }.freeze
117
+ private_constant :GROUP_FOR_TYPE
118
+
91
119
  # Define a +recursive_?+ predicate method for the given node kind.
92
120
  private_class_method def self.def_recursive_literal_predicate(kind) # rubocop:disable Metrics/MethodLength
93
121
  recursive_kind = "recursive_#{kind}?"
@@ -126,6 +154,16 @@ module RuboCop
126
154
  end
127
155
  end
128
156
 
157
+ # Determine if the node is one of several node types in a single query
158
+ # Allows specific single node types, as well as "grouped" types
159
+ # (e.g. `:boolean` for `:true` or `:false`)
160
+ def type?(*types)
161
+ return true if types.include?(type)
162
+
163
+ group_type = GROUP_FOR_TYPE[type]
164
+ !group_type.nil? && types.include?(group_type)
165
+ end
166
+
129
167
  (Parser::Meta::NODE_TYPES - [:send]).each do |node_type|
130
168
  method_name = "#{node_type.to_s.gsub(/\W/, '')}_type?"
131
169
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
@@ -312,13 +350,12 @@ module RuboCop
312
350
  def_node_matcher :str_content, '(str $_)'
313
351
 
314
352
  def const_name
315
- return unless const_type?
353
+ return unless const_type? || casgn_type?
316
354
 
317
- namespace, name = *self
318
355
  if namespace && !namespace.cbase_type?
319
- "#{namespace.const_name}::#{name}"
356
+ "#{namespace.const_name}::#{short_name}"
320
357
  else
321
- name.to_s
358
+ short_name.to_s
322
359
  end
323
360
  end
324
361
 
@@ -460,11 +497,11 @@ module RuboCop
460
497
  end
461
498
 
462
499
  def parenthesized_call?
463
- loc.respond_to?(:begin) && loc.begin&.is?('(')
500
+ loc_is?(:begin, '(')
464
501
  end
465
502
 
466
503
  def call_type?
467
- send_type? || csend_type?
504
+ GROUP_FOR_TYPE[type] == :call
468
505
  end
469
506
 
470
507
  def chained?
@@ -476,27 +513,38 @@ module RuboCop
476
513
  end
477
514
 
478
515
  def argument_type?
479
- ARGUMENT_TYPES.include?(type)
516
+ GROUP_FOR_TYPE[type] == :argument
480
517
  end
481
518
 
482
519
  def boolean_type?
483
- true_type? || false_type?
520
+ GROUP_FOR_TYPE[type] == :boolean
484
521
  end
485
522
 
486
523
  def numeric_type?
487
- int_type? || float_type? || rational_type? || complex_type?
524
+ GROUP_FOR_TYPE[type] == :numeric
488
525
  end
489
526
 
490
527
  def range_type?
491
- irange_type? || erange_type?
528
+ GROUP_FOR_TYPE[type] == :range
492
529
  end
493
530
 
494
531
  def guard_clause?
495
- node = and_type? || or_type? ? rhs : self
532
+ node = operator_keyword? ? rhs : self
496
533
 
497
534
  node.match_guard_clause?
498
535
  end
499
536
 
537
+ # Shortcut to safely test a particular location, even if
538
+ # this location does not exist or is `nil`
539
+ def loc_is?(which_loc, str)
540
+ return false unless loc.respond_to?(which_loc)
541
+
542
+ location = loc.public_send(which_loc)
543
+ return false unless location
544
+
545
+ location.is?(str)
546
+ end
547
+
500
548
  # @!method match_guard_clause?(node = self)
501
549
  def_node_matcher :match_guard_clause?, <<~PATTERN
502
550
  [${(send nil? {:raise :fail} ...) return break next} single_line?]
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module AST
5
5
  module Version
6
- STRING = '1.33.0'
6
+ STRING = '1.37.0'
7
7
  end
8
8
  end
9
9
  end
data/lib/rubocop/ast.rb CHANGED
@@ -60,6 +60,7 @@ require_relative 'ast/node/in_pattern_node'
60
60
  require_relative 'ast/node/index_node'
61
61
  require_relative 'ast/node/indexasgn_node'
62
62
  require_relative 'ast/node/int_node'
63
+ require_relative 'ast/node/keyword_begin_node'
63
64
  require_relative 'ast/node/keyword_splat_node'
64
65
  require_relative 'ast/node/lambda_node'
65
66
  require_relative 'ast/node/masgn_node'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-ast
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.33.0
4
+ version: 1.37.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-10-29 00:00:00.000000000 Z
13
+ date: 2024-12-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: parser
@@ -69,6 +69,7 @@ files:
69
69
  - lib/rubocop/ast/node/index_node.rb
70
70
  - lib/rubocop/ast/node/indexasgn_node.rb
71
71
  - lib/rubocop/ast/node/int_node.rb
72
+ - lib/rubocop/ast/node/keyword_begin_node.rb
72
73
  - lib/rubocop/ast/node/keyword_splat_node.rb
73
74
  - lib/rubocop/ast/node/lambda_node.rb
74
75
  - lib/rubocop/ast/node/masgn_node.rb