rubocop-ast 0.0.3 → 0.4.1
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 +4 -4
- data/README.md +21 -4
- data/lib/rubocop/ast.rb +9 -1
- data/lib/rubocop/ast/builder.rb +8 -1
- data/lib/rubocop/ast/ext/range.rb +28 -0
- data/lib/rubocop/ast/ext/set.rb +12 -0
- data/lib/rubocop/ast/node.rb +81 -10
- data/lib/rubocop/ast/node/array_node.rb +2 -8
- data/lib/rubocop/ast/node/block_node.rb +1 -1
- data/lib/rubocop/ast/node/break_node.rb +1 -6
- data/lib/rubocop/ast/node/case_match_node.rb +3 -9
- data/lib/rubocop/ast/node/case_node.rb +13 -9
- data/lib/rubocop/ast/node/const_node.rb +65 -0
- data/lib/rubocop/ast/node/def_node.rb +5 -24
- data/lib/rubocop/ast/node/defined_node.rb +2 -0
- data/lib/rubocop/ast/node/float_node.rb +1 -0
- data/lib/rubocop/ast/node/forward_args_node.rb +15 -0
- data/lib/rubocop/ast/node/hash_node.rb +21 -8
- data/lib/rubocop/ast/node/if_node.rb +7 -14
- data/lib/rubocop/ast/node/index_node.rb +48 -0
- data/lib/rubocop/ast/node/indexasgn_node.rb +50 -0
- data/lib/rubocop/ast/node/int_node.rb +1 -0
- data/lib/rubocop/ast/node/lambda_node.rb +65 -0
- data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +2 -8
- data/lib/rubocop/ast/node/mixin/method_identifier_predicates.rb +99 -3
- data/lib/rubocop/ast/node/mixin/parameterized_node.rb +56 -0
- data/lib/rubocop/ast/node/next_node.rb +12 -0
- data/lib/rubocop/ast/node/pair_node.rb +2 -2
- data/lib/rubocop/ast/node/regexp_node.rb +56 -0
- data/lib/rubocop/ast/node/resbody_node.rb +21 -0
- data/lib/rubocop/ast/node/rescue_node.rb +49 -0
- data/lib/rubocop/ast/node/return_node.rb +1 -13
- data/lib/rubocop/ast/node/send_node.rb +9 -2
- data/lib/rubocop/ast/node/super_node.rb +2 -0
- data/lib/rubocop/ast/node/when_node.rb +3 -9
- data/lib/rubocop/ast/node/yield_node.rb +2 -0
- data/lib/rubocop/ast/node_pattern.rb +184 -115
- data/lib/rubocop/ast/processed_source.rb +98 -16
- data/lib/rubocop/ast/traversal.rb +6 -4
- data/lib/rubocop/ast/version.rb +1 -1
- metadata +16 -9
- data/lib/rubocop/ast/node/retry_node.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bf5651a5da2be43d773d152c2f2260dfd1850ce1075aca7c4d21c08dd31a92a
|
4
|
+
data.tar.gz: c9addcd67e29e797109dc2f523c9c2094f94908b40c2e60c56061d6a8bf0e0f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1aa33edeacd95a65468093b80248a5908c69d30bf7d19afd6141044d00830f31c12aa489caf8ef705364d63771cade73651d9697635ab22941137df467ce4e92
|
7
|
+
data.tar.gz: fb820b52d69df72ab17a5ee06d06bdf7256b3318d8094b96467f79d314bad1b52bcb3938cb2ef98ca07b300f56132ac14921ef24aadf299d4c5754bb118b119f
|
data/README.md
CHANGED
@@ -2,12 +2,16 @@
|
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/rubocop-ast)
|
4
4
|
[](https://github.com/rubocop-hq/rubocop-ast/actions?query=workflow%3ACI)
|
5
|
+
[](https://codeclimate.com/github/rubocop-hq/rubocop-ast/test_coverage)
|
6
|
+
[](https://codeclimate.com/github/rubocop-hq/rubocop-ast/maintainability)
|
5
7
|
|
6
8
|
Contains the classes needed by [RuboCop](https://github.com/rubocop-hq/rubocop) to deal with Ruby's AST, in particular:
|
7
|
-
* `RuboCop::AST::Node`
|
8
|
-
* `RuboCop::AST::NodePattern` ([doc](manual/node_pattern.md))
|
9
9
|
|
10
|
-
|
10
|
+
* `RuboCop::AST::Node` ([doc](docs/modules/ROOT/pages/node_types.adoc))
|
11
|
+
* `RuboCop::AST::NodePattern` ([doc](docs/modules/ROOT/pages/node_pattern.adoc))
|
12
|
+
|
13
|
+
This gem may be used independently from the main RuboCop gem. It was extracted from RuboCop in version 0.84 and its only
|
14
|
+
dependency is the [parser](https://github.com/whitequark/parser) gem, which `rubocop-ast` extends.
|
11
15
|
|
12
16
|
## Installation
|
13
17
|
|
@@ -25,7 +29,20 @@ gem 'rubocop-ast'
|
|
25
29
|
|
26
30
|
## Usage
|
27
31
|
|
28
|
-
Refer to the documentation of `RuboCop::AST::Node` and [`RuboCop::AST::NodePattern`](
|
32
|
+
Refer to the documentation of [`RuboCop::AST::Node`](docs/modules/ROOT/pages/node_types.adoc) and [`RuboCop::AST::NodePattern`](docs/modules/ROOT/pages/node_pattern.adoc)
|
33
|
+
|
34
|
+
See the [docs site](https://docs.rubocop.org/rubocop-ast) for more details.
|
35
|
+
|
36
|
+
### Parser compatibility switches
|
37
|
+
|
38
|
+
This gem, by default, uses most [legacy AST output from parser](https://github.com/whitequark/parser/#usage), except for `emit_forward_arg` which is set to `true`.
|
39
|
+
|
40
|
+
The main `RuboCop` gem uses these defaults (and is currently only compatible with these), but this gem can be used separately from `RuboCop` and is meant to be compatible with all settings. For example, to have `-> { ... }` emitted
|
41
|
+
as `LambdaNode` instead of `SendNode`:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
RuboCop::AST::Builder.emit_lambda = true
|
45
|
+
```
|
29
46
|
|
30
47
|
## Contributing
|
31
48
|
|
data/lib/rubocop/ast.rb
CHANGED
@@ -2,7 +2,10 @@
|
|
2
2
|
|
3
3
|
require 'parser'
|
4
4
|
require 'forwardable'
|
5
|
+
require 'set'
|
5
6
|
|
7
|
+
require_relative 'ast/ext/range'
|
8
|
+
require_relative 'ast/ext/set'
|
6
9
|
require_relative 'ast/node_pattern'
|
7
10
|
require_relative 'ast/sexp'
|
8
11
|
require_relative 'ast/node'
|
@@ -26,6 +29,7 @@ require_relative 'ast/node/break_node'
|
|
26
29
|
require_relative 'ast/node/case_match_node'
|
27
30
|
require_relative 'ast/node/case_node'
|
28
31
|
require_relative 'ast/node/class_node'
|
32
|
+
require_relative 'ast/node/const_node'
|
29
33
|
require_relative 'ast/node/def_node'
|
30
34
|
require_relative 'ast/node/defined_node'
|
31
35
|
require_relative 'ast/node/ensure_node'
|
@@ -34,15 +38,19 @@ require_relative 'ast/node/forward_args_node'
|
|
34
38
|
require_relative 'ast/node/float_node'
|
35
39
|
require_relative 'ast/node/hash_node'
|
36
40
|
require_relative 'ast/node/if_node'
|
41
|
+
require_relative 'ast/node/index_node'
|
42
|
+
require_relative 'ast/node/indexasgn_node'
|
37
43
|
require_relative 'ast/node/int_node'
|
38
44
|
require_relative 'ast/node/keyword_splat_node'
|
45
|
+
require_relative 'ast/node/lambda_node'
|
39
46
|
require_relative 'ast/node/module_node'
|
47
|
+
require_relative 'ast/node/next_node'
|
40
48
|
require_relative 'ast/node/or_node'
|
41
49
|
require_relative 'ast/node/pair_node'
|
42
50
|
require_relative 'ast/node/range_node'
|
43
51
|
require_relative 'ast/node/regexp_node'
|
52
|
+
require_relative 'ast/node/rescue_node'
|
44
53
|
require_relative 'ast/node/resbody_node'
|
45
|
-
require_relative 'ast/node/retry_node'
|
46
54
|
require_relative 'ast/node/return_node'
|
47
55
|
require_relative 'ast/node/self_class_node'
|
48
56
|
require_relative 'ast/node/send_node'
|
data/lib/rubocop/ast/builder.rb
CHANGED
@@ -14,6 +14,8 @@ module RuboCop
|
|
14
14
|
# parser = Parser::Ruby25.new(builder)
|
15
15
|
# root_node = parser.parse(buffer)
|
16
16
|
class Builder < Parser::Builders::Default
|
17
|
+
self.emit_forward_arg = true
|
18
|
+
|
17
19
|
NODE_MAP = {
|
18
20
|
and: AndNode,
|
19
21
|
alias: AliasNode,
|
@@ -25,6 +27,7 @@ module RuboCop
|
|
25
27
|
case_match: CaseMatchNode,
|
26
28
|
case: CaseNode,
|
27
29
|
class: ClassNode,
|
30
|
+
const: ConstNode,
|
28
31
|
def: DefNode,
|
29
32
|
defined?: DefinedNode,
|
30
33
|
defs: DefNode,
|
@@ -35,15 +38,19 @@ module RuboCop
|
|
35
38
|
hash: HashNode,
|
36
39
|
if: IfNode,
|
37
40
|
int: IntNode,
|
41
|
+
index: IndexNode,
|
42
|
+
indexasgn: IndexasgnNode,
|
38
43
|
irange: RangeNode,
|
39
44
|
erange: RangeNode,
|
40
45
|
kwsplat: KeywordSplatNode,
|
46
|
+
lambda: LambdaNode,
|
41
47
|
module: ModuleNode,
|
48
|
+
next: NextNode,
|
42
49
|
or: OrNode,
|
43
50
|
pair: PairNode,
|
44
51
|
regexp: RegexpNode,
|
52
|
+
rescue: RescueNode,
|
45
53
|
resbody: ResbodyNode,
|
46
|
-
retry: RetryNode,
|
47
54
|
return: ReturnNode,
|
48
55
|
csend: SendNode,
|
49
56
|
send: SendNode,
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
module Ext
|
6
|
+
# Extensions to Parser::AST::Range
|
7
|
+
module Range
|
8
|
+
# @return [Range] the range of line numbers for the node
|
9
|
+
# If `exclude_end` is `true`, then the range will be exclusive.
|
10
|
+
#
|
11
|
+
# Assume that `node` corresponds to the following array literal:
|
12
|
+
#
|
13
|
+
# [
|
14
|
+
# :foo,
|
15
|
+
# :bar
|
16
|
+
# ]
|
17
|
+
#
|
18
|
+
# node.loc.begin.line_span # => 1..1
|
19
|
+
# node.loc.expression.line_span(exclude_end: true) # => 1...4
|
20
|
+
def line_span(exclude_end: false)
|
21
|
+
::Range.new(first_line, last_line, exclude_end)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
::Parser::Source::Range.include ::RuboCop::AST::Ext::Range
|
data/lib/rubocop/ast/node.rb
CHANGED
@@ -38,12 +38,14 @@ module RuboCop
|
|
38
38
|
IMMUTABLE_LITERALS = (LITERALS - MUTABLE_LITERALS).freeze
|
39
39
|
|
40
40
|
EQUALS_ASSIGNMENTS = %i[lvasgn ivasgn cvasgn gvasgn
|
41
|
-
casgn masgn].freeze
|
41
|
+
casgn masgn rasgn mrasgn].freeze
|
42
42
|
SHORTHAND_ASSIGNMENTS = %i[op_asgn or_asgn and_asgn].freeze
|
43
43
|
ASSIGNMENTS = (EQUALS_ASSIGNMENTS + SHORTHAND_ASSIGNMENTS).freeze
|
44
44
|
|
45
45
|
BASIC_CONDITIONALS = %i[if while until].freeze
|
46
46
|
CONDITIONALS = [*BASIC_CONDITIONALS, :case].freeze
|
47
|
+
POST_CONDITION_LOOP_TYPES = %i[while_post until_post].freeze
|
48
|
+
LOOP_TYPES = (POST_CONDITION_LOOP_TYPES + %i[while until for]).freeze
|
47
49
|
VARIABLES = %i[ivar gvar cvar lvar].freeze
|
48
50
|
REFERENCES = %i[nth_ref back_ref].freeze
|
49
51
|
KEYWORDS = %i[alias and break case class def defs defined?
|
@@ -53,6 +55,7 @@ module RuboCop
|
|
53
55
|
yield].freeze
|
54
56
|
OPERATOR_KEYWORDS = %i[and or].freeze
|
55
57
|
SPECIAL_KEYWORDS = %w[__FILE__ __LINE__ __ENCODING__].freeze
|
58
|
+
ARGUMENT_TYPES = %i[arg optarg restarg kwarg kwoptarg kwrestarg blockarg].freeze
|
56
59
|
|
57
60
|
# @see https://www.rubydoc.info/gems/ast/AST/Node:initialize
|
58
61
|
def initialize(type, children = [], properties = {})
|
@@ -113,12 +116,50 @@ module RuboCop
|
|
113
116
|
|
114
117
|
# Returns the index of the receiver node in its siblings. (Sibling index
|
115
118
|
# uses zero based numbering.)
|
119
|
+
# Use is discouraged, this is a potentially slow method.
|
116
120
|
#
|
117
|
-
# @return [Integer] the index of the receiver node in its siblings
|
121
|
+
# @return [Integer, nil] the index of the receiver node in its siblings
|
118
122
|
def sibling_index
|
119
123
|
parent&.children&.index { |sibling| sibling.equal?(self) }
|
120
124
|
end
|
121
125
|
|
126
|
+
# Use is discouraged, this is a potentially slow method and can lead
|
127
|
+
# to even slower algorithms
|
128
|
+
# @return [Node, nil] the right (aka next) sibling
|
129
|
+
def right_sibling
|
130
|
+
return unless parent
|
131
|
+
|
132
|
+
parent.children[sibling_index + 1].freeze
|
133
|
+
end
|
134
|
+
|
135
|
+
# Use is discouraged, this is a potentially slow method and can lead
|
136
|
+
# to even slower algorithms
|
137
|
+
# @return [Node, nil] the left (aka previous) sibling
|
138
|
+
def left_sibling
|
139
|
+
i = sibling_index
|
140
|
+
return if i.nil? || i.zero?
|
141
|
+
|
142
|
+
parent.children[i - 1].freeze
|
143
|
+
end
|
144
|
+
|
145
|
+
# Use is discouraged, this is a potentially slow method and can lead
|
146
|
+
# to even slower algorithms
|
147
|
+
# @return [Array<Node>] the left (aka previous) siblings
|
148
|
+
def left_siblings
|
149
|
+
return [].freeze unless parent
|
150
|
+
|
151
|
+
parent.children[0...sibling_index].freeze
|
152
|
+
end
|
153
|
+
|
154
|
+
# Use is discouraged, this is a potentially slow method and can lead
|
155
|
+
# to even slower algorithms
|
156
|
+
# @return [Array<Node>] the right (aka next) siblings
|
157
|
+
def right_siblings
|
158
|
+
return [].freeze unless parent
|
159
|
+
|
160
|
+
parent.children[sibling_index + 1..-1].freeze
|
161
|
+
end
|
162
|
+
|
122
163
|
# Common destructuring method. This can be used to normalize
|
123
164
|
# destructuring for different variations of the node.
|
124
165
|
# Some node types override this with their own custom
|
@@ -310,8 +351,8 @@ module RuboCop
|
|
310
351
|
def_node_matcher :defined_module0, <<~PATTERN
|
311
352
|
{(class (const $_ $_) ...)
|
312
353
|
(module (const $_ $_) ...)
|
313
|
-
(casgn $_ $_ (send (
|
314
|
-
(casgn $_ $_ (block (send (
|
354
|
+
(casgn $_ $_ (send #global_const?({:Class :Module}) :new ...))
|
355
|
+
(casgn $_ $_ (block (send #global_const?({:Class :Module}) :new ...) ...))}
|
315
356
|
PATTERN
|
316
357
|
|
317
358
|
private :defined_module0
|
@@ -425,6 +466,15 @@ module RuboCop
|
|
425
466
|
CONDITIONALS.include?(type)
|
426
467
|
end
|
427
468
|
|
469
|
+
def post_condition_loop?
|
470
|
+
POST_CONDITION_LOOP_TYPES.include?(type)
|
471
|
+
end
|
472
|
+
|
473
|
+
# Note: `loop { }` is a normal method call and thus not a loop keyword.
|
474
|
+
def loop_keyword?
|
475
|
+
LOOP_TYPES.include?(type)
|
476
|
+
end
|
477
|
+
|
428
478
|
def keyword?
|
429
479
|
return true if special_keyword? || send_type? && prefix_not?
|
430
480
|
return false unless KEYWORDS.include?(type)
|
@@ -456,6 +506,10 @@ module RuboCop
|
|
456
506
|
parent&.send_type? && parent.arguments.include?(self)
|
457
507
|
end
|
458
508
|
|
509
|
+
def argument_type?
|
510
|
+
ARGUMENT_TYPES.include?(type)
|
511
|
+
end
|
512
|
+
|
459
513
|
def boolean_type?
|
460
514
|
true_type? || false_type?
|
461
515
|
end
|
@@ -480,16 +534,33 @@ module RuboCop
|
|
480
534
|
|
481
535
|
def_node_matcher :proc?, <<~PATTERN
|
482
536
|
{(block (send nil? :proc) ...)
|
483
|
-
(block (send (
|
484
|
-
(send (
|
537
|
+
(block (send #global_const?(:Proc) :new) ...)
|
538
|
+
(send #global_const?(:Proc) :new)}
|
485
539
|
PATTERN
|
486
540
|
|
487
541
|
def_node_matcher :lambda?, '({block numblock} (send nil? :lambda) ...)'
|
488
542
|
def_node_matcher :lambda_or_proc?, '{lambda? proc?}'
|
489
543
|
|
544
|
+
def_node_matcher :global_const?, '(const {nil? cbase} %1)'
|
545
|
+
|
490
546
|
def_node_matcher :class_constructor?, <<~PATTERN
|
491
|
-
{ (send (
|
492
|
-
(block (send (
|
547
|
+
{ (send #global_const?({:Class :Module}) :new ...)
|
548
|
+
(block (send #global_const?({:Class :Module}) :new ...) ...)}
|
549
|
+
PATTERN
|
550
|
+
|
551
|
+
def_node_matcher :struct_constructor?, <<~PATTERN
|
552
|
+
(block (send #global_const?(:Struct) :new ...) _ $_)
|
553
|
+
PATTERN
|
554
|
+
|
555
|
+
def_node_matcher :class_definition?, <<~PATTERN
|
556
|
+
{(class _ _ $_)
|
557
|
+
(sclass _ $_)
|
558
|
+
(block (send #global_const?({:Struct :Class}) :new ...) _ $_)}
|
559
|
+
PATTERN
|
560
|
+
|
561
|
+
def_node_matcher :module_definition?, <<~PATTERN
|
562
|
+
{(module _ $_)
|
563
|
+
(block (send #global_const?(:Module) :new ...) _ $_)}
|
493
564
|
PATTERN
|
494
565
|
|
495
566
|
# Some expressions are evaluated for their value, some for their side
|
@@ -500,7 +571,7 @@ module RuboCop
|
|
500
571
|
# So, does the return value of this node matter? If we changed it to
|
501
572
|
# `(...; nil)`, might that affect anything?
|
502
573
|
#
|
503
|
-
# rubocop:disable Metrics/MethodLength
|
574
|
+
# rubocop:disable Metrics/MethodLength
|
504
575
|
def value_used?
|
505
576
|
# Be conservative and return true if we're not sure.
|
506
577
|
return false if parent.nil?
|
@@ -522,7 +593,7 @@ module RuboCop
|
|
522
593
|
true
|
523
594
|
end
|
524
595
|
end
|
525
|
-
# rubocop:enable Metrics/MethodLength
|
596
|
+
# rubocop:enable Metrics/MethodLength
|
526
597
|
|
527
598
|
# Some expressions are evaluated for their value, some for their side
|
528
599
|
# effects, and some for both.
|
@@ -14,15 +14,9 @@ module RuboCop
|
|
14
14
|
# Returns an array of all value nodes in the `array` literal.
|
15
15
|
#
|
16
16
|
# @return [Array<Node>] an array of value nodes
|
17
|
-
|
18
|
-
each_child_node.to_a
|
19
|
-
end
|
17
|
+
alias values children
|
20
18
|
|
21
|
-
#
|
22
|
-
#
|
23
|
-
# @yieldparam [Node] node each node
|
24
|
-
# @return [self] if a block is given
|
25
|
-
# @return [Enumerator] if no block is given
|
19
|
+
# @deprecated Use `values.each` (a.k.a. `children.each`)
|
26
20
|
def each_value(&block)
|
27
21
|
return to_enum(__method__) unless block_given?
|
28
22
|
|
@@ -6,12 +6,7 @@ module RuboCop
|
|
6
6
|
# plain node when the builder constructs the AST, making its methods
|
7
7
|
# available to all `break` nodes within RuboCop.
|
8
8
|
class BreakNode < Node
|
9
|
-
include
|
10
|
-
include ParameterizedNode
|
11
|
-
|
12
|
-
def arguments
|
13
|
-
[]
|
14
|
-
end
|
9
|
+
include ParameterizedNode::WrappedArguments
|
15
10
|
end
|
16
11
|
end
|
17
12
|
end
|
@@ -15,17 +15,11 @@ module RuboCop
|
|
15
15
|
'case'
|
16
16
|
end
|
17
17
|
|
18
|
-
#
|
19
|
-
|
20
|
-
#
|
21
|
-
# @return [self] if a block is given
|
22
|
-
# @return [Enumerator] if no block is given
|
23
|
-
def each_in_pattern
|
18
|
+
# @deprecated Use `in_pattern_branches.each`
|
19
|
+
def each_in_pattern(&block)
|
24
20
|
return in_pattern_branches.to_enum(__method__) unless block_given?
|
25
21
|
|
26
|
-
in_pattern_branches.each
|
27
|
-
yield condition
|
28
|
-
end
|
22
|
+
in_pattern_branches.each(&block)
|
29
23
|
|
30
24
|
self
|
31
25
|
end
|
@@ -15,17 +15,11 @@ module RuboCop
|
|
15
15
|
'case'
|
16
16
|
end
|
17
17
|
|
18
|
-
#
|
19
|
-
|
20
|
-
#
|
21
|
-
# @return [self] if a block is given
|
22
|
-
# @return [Enumerator] if no block is given
|
23
|
-
def each_when
|
18
|
+
# @deprecated Use `when_branches.each`
|
19
|
+
def each_when(&block)
|
24
20
|
return when_branches.to_enum(__method__) unless block_given?
|
25
21
|
|
26
|
-
when_branches.each
|
27
|
-
yield condition
|
28
|
-
end
|
22
|
+
when_branches.each(&block)
|
29
23
|
|
30
24
|
self
|
31
25
|
end
|
@@ -37,6 +31,16 @@ module RuboCop
|
|
37
31
|
node_parts[1...-1]
|
38
32
|
end
|
39
33
|
|
34
|
+
# Returns an array of all the when branches in the `case` statement.
|
35
|
+
#
|
36
|
+
# @return [Array<Node, nil>] an array of the bodies of the when branches
|
37
|
+
# and the else (if any). Note that these bodies could be nil.
|
38
|
+
def branches
|
39
|
+
bodies = when_branches.map(&:body)
|
40
|
+
bodies.push(else_branch) if else?
|
41
|
+
bodies
|
42
|
+
end
|
43
|
+
|
40
44
|
# Returns the else branch of the `case` statement, if any.
|
41
45
|
#
|
42
46
|
# @return [Node] the else branch node of the `case` statement
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# A node extension for `const` nodes.
|
6
|
+
class ConstNode < Node
|
7
|
+
# The `send` node associated with this block.
|
8
|
+
#
|
9
|
+
# @return [Node, nil] the node associated with the scope (e.g. cbase, const, ...)
|
10
|
+
def namespace
|
11
|
+
children[0]
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [Symbol] the demodulized name of the constant: "::Foo::Bar" => :Bar
|
15
|
+
def short_name
|
16
|
+
children[1]
|
17
|
+
end
|
18
|
+
|
19
|
+
# The body of this block.
|
20
|
+
#
|
21
|
+
# @return [Boolean] if the constant is a Module / Class, according to the standard convention.
|
22
|
+
# Note: some classes might have uppercase in which case this method
|
23
|
+
# returns false
|
24
|
+
def module_name?
|
25
|
+
short_name.match?(/[[:lower:]]/)
|
26
|
+
end
|
27
|
+
alias class_name? module_name?
|
28
|
+
|
29
|
+
# @return [Boolean] if the constant starts with `::` (aka s(:cbase))
|
30
|
+
def absolute?
|
31
|
+
return false unless namespace
|
32
|
+
|
33
|
+
each_path.first.cbase_type?
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Boolean] if the constant does not start with `::` (aka s(:cbase))
|
37
|
+
def relative?
|
38
|
+
!absolute?
|
39
|
+
end
|
40
|
+
|
41
|
+
# Yield nodes for the namespace
|
42
|
+
#
|
43
|
+
# For `::Foo::Bar::BAZ` => yields:
|
44
|
+
# s(:cbase), then
|
45
|
+
# s(:const, :Foo), then
|
46
|
+
# s(:const, s(:const, :Foo), :Bar)
|
47
|
+
def each_path(&block)
|
48
|
+
return to_enum(__method__) unless block_given?
|
49
|
+
|
50
|
+
descendants = []
|
51
|
+
last = self
|
52
|
+
loop do
|
53
|
+
last = last.children.first
|
54
|
+
break if last.nil?
|
55
|
+
|
56
|
+
descendants << last
|
57
|
+
break unless last.const_type?
|
58
|
+
end
|
59
|
+
descendants.reverse_each(&block)
|
60
|
+
|
61
|
+
self
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|