transpec 1.9.3 → 1.10.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 +4 -4
- data/.rubocop.yml +1 -1
- data/.travis.yml +1 -1
- data/CHANGELOG.md +5 -0
- data/CONTRIBUTING.md +19 -0
- data/README.md +78 -9
- data/README.md.erb +68 -10
- data/lib/transpec/annotatable.rb +16 -0
- data/lib/transpec/cli.rb +35 -27
- data/lib/transpec/configuration.rb +1 -0
- data/lib/transpec/conversion_error.rb +23 -0
- data/lib/transpec/converter.rb +59 -50
- data/lib/transpec/dynamic_analyzer.rb +13 -29
- data/lib/transpec/dynamic_analyzer/rewriter.rb +3 -10
- data/lib/transpec/dynamic_analyzer/runtime_data.rb +16 -8
- data/lib/transpec/file_finder.rb +1 -1
- data/lib/transpec/git.rb +1 -1
- data/lib/transpec/option_parser.rb +12 -10
- data/lib/transpec/project.rb +3 -3
- data/lib/transpec/record.rb +19 -2
- data/lib/transpec/report.rb +29 -13
- data/lib/transpec/rspec_version.rb +7 -7
- data/lib/transpec/static_context_inspector.rb +1 -5
- data/lib/transpec/syntax.rb +11 -16
- data/lib/transpec/syntax/be_boolean.rb +1 -1
- data/lib/transpec/syntax/be_close.rb +1 -1
- data/lib/transpec/syntax/current_example.rb +88 -0
- data/lib/transpec/syntax/double.rb +1 -1
- data/lib/transpec/syntax/example.rb +60 -54
- data/lib/transpec/syntax/have.rb +27 -15
- data/lib/transpec/syntax/have/have_record.rb +12 -0
- data/lib/transpec/syntax/have/source_builder.rb +18 -16
- data/lib/transpec/syntax/its.rb +12 -11
- data/lib/transpec/syntax/matcher_definition.rb +1 -1
- data/lib/transpec/syntax/method_stub.rb +3 -7
- data/lib/transpec/syntax/mixin/matcher_owner.rb +2 -2
- data/lib/transpec/syntax/mixin/monkey_patch.rb +3 -5
- data/lib/transpec/syntax/mixin/monkey_patch_any_instance.rb +2 -4
- data/lib/transpec/syntax/mixin/owned_matcher.rb +1 -4
- data/lib/transpec/syntax/mixin/send.rb +7 -9
- data/lib/transpec/syntax/oneliner_should.rb +4 -4
- data/lib/transpec/syntax/operator.rb +27 -11
- data/lib/transpec/syntax/pending.rb +110 -0
- data/lib/transpec/syntax/raise_error.rb +1 -1
- data/lib/transpec/syntax/receive.rb +4 -4
- data/lib/transpec/syntax/rspec_configure/framework.rb +3 -3
- data/lib/transpec/syntax/should.rb +2 -2
- data/lib/transpec/syntax/should_receive.rb +3 -3
- data/lib/transpec/util.rb +38 -6
- data/lib/transpec/version.rb +2 -2
- data/spec/support/file_helper.rb +1 -1
- data/spec/support/shared_context.rb +3 -8
- data/spec/transpec/cli_spec.rb +63 -1
- data/spec/transpec/configuration_spec.rb +1 -0
- data/spec/transpec/converter_spec.rb +106 -15
- data/spec/transpec/dynamic_analyzer/rewriter_spec.rb +12 -52
- data/spec/transpec/dynamic_analyzer_spec.rb +2 -2
- data/spec/transpec/option_parser_spec.rb +3 -2
- data/spec/transpec/report_spec.rb +33 -4
- data/spec/transpec/rspec_version_spec.rb +5 -2
- data/spec/transpec/syntax/current_example_spec.rb +267 -0
- data/spec/transpec/syntax/example_spec.rb +156 -122
- data/spec/transpec/syntax/have_spec.rb +43 -32
- data/spec/transpec/syntax/method_stub_spec.rb +8 -0
- data/spec/transpec/syntax/operator_spec.rb +67 -2
- data/spec/transpec/syntax/pending_spec.rb +375 -0
- metadata +12 -4
- data/lib/transpec/context_error.rb +0 -23
@@ -17,14 +17,12 @@ module Transpec
|
|
17
17
|
code << " && respond_to?(#{method.inspect})"
|
18
18
|
end
|
19
19
|
|
20
|
-
rewriter.register_request(
|
20
|
+
rewriter.register_request(node, key, code, :context)
|
21
21
|
end
|
22
22
|
|
23
23
|
def check_syntax_availability(key)
|
24
|
-
|
25
|
-
|
26
|
-
if node_data
|
27
|
-
node_data[key].result
|
24
|
+
if runtime_data.present?(node, key)
|
25
|
+
runtime_data[node, key]
|
28
26
|
else
|
29
27
|
static_context_inspector.send(key)
|
30
28
|
end
|
@@ -32,9 +32,7 @@ module Transpec
|
|
32
32
|
|
33
33
|
def any_instance?
|
34
34
|
return true unless any_instance_target_node.nil?
|
35
|
-
|
36
|
-
return false unless node_data && node_data[:any_instance_target_class_name]
|
37
|
-
!node_data[:any_instance_target_class_name].result.nil?
|
35
|
+
!runtime_data[subject_node, :any_instance_target_class_name].nil?
|
38
36
|
end
|
39
37
|
|
40
38
|
private
|
@@ -45,7 +43,7 @@ module Transpec
|
|
45
43
|
if any_instance_target_node
|
46
44
|
any_instance_target_node.loc.expression.source
|
47
45
|
else
|
48
|
-
|
46
|
+
runtime_data[subject_node, :any_instance_target_class_name]
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
@@ -19,11 +19,8 @@ module Transpec
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def initialize(node, expectation, source_rewriter = nil, runtime_data = nil, report = nil)
|
22
|
-
|
22
|
+
super(node, source_rewriter, runtime_data, report)
|
23
23
|
@expectation = expectation
|
24
|
-
@source_rewriter = source_rewriter
|
25
|
-
@runtime_data = runtime_data
|
26
|
-
@report = report || Report.new
|
27
24
|
end
|
28
25
|
end
|
29
26
|
end
|
@@ -34,9 +34,7 @@ module Transpec
|
|
34
34
|
return unless runtime_data
|
35
35
|
receiver_node, method_name, *_ = *node
|
36
36
|
target_node = receiver_node ? receiver_node : node
|
37
|
-
|
38
|
-
return unless (eval_data = node_data[source_location_key(method_name)])
|
39
|
-
eval_data.result
|
37
|
+
runtime_data[target_node, source_location_key(method_name)]
|
40
38
|
end
|
41
39
|
|
42
40
|
def source_location_key(method_name)
|
@@ -50,7 +48,7 @@ module Transpec
|
|
50
48
|
target_node = receiver_node
|
51
49
|
target_object_type = :object
|
52
50
|
else
|
53
|
-
target_node =
|
51
|
+
target_node = node
|
54
52
|
target_object_type = :context
|
55
53
|
end
|
56
54
|
|
@@ -61,23 +59,23 @@ module Transpec
|
|
61
59
|
end
|
62
60
|
|
63
61
|
def receiver_node
|
64
|
-
|
62
|
+
node.children[0]
|
65
63
|
end
|
66
64
|
|
67
65
|
def method_name
|
68
|
-
|
66
|
+
node.children[1]
|
69
67
|
end
|
70
68
|
|
71
69
|
def arg_node
|
72
|
-
|
70
|
+
node.children[2]
|
73
71
|
end
|
74
72
|
|
75
73
|
def arg_nodes
|
76
|
-
|
74
|
+
node.children[2..-1]
|
77
75
|
end
|
78
76
|
|
79
77
|
def selector_range
|
80
|
-
|
78
|
+
node.loc.selector
|
81
79
|
end
|
82
80
|
|
83
81
|
def receiver_range
|
@@ -43,7 +43,7 @@ module Transpec
|
|
43
43
|
|
44
44
|
have_matcher.convert_to_standard_expectation!
|
45
45
|
|
46
|
-
|
46
|
+
report.records << OnelinerShouldHaveRecord.new(self, have_matcher)
|
47
47
|
end
|
48
48
|
|
49
49
|
# rubocop:disable LineLength
|
@@ -61,7 +61,7 @@ module Transpec
|
|
61
61
|
@current_syntax_type = :expect
|
62
62
|
have_matcher.convert_to_standard_expectation!
|
63
63
|
|
64
|
-
|
64
|
+
report.records << OnelinerShouldHaveRecord.new(self, have_matcher, negative_form)
|
65
65
|
end
|
66
66
|
|
67
67
|
def example_has_description?
|
@@ -111,7 +111,7 @@ module Transpec
|
|
111
111
|
def example_block_node
|
112
112
|
return @example_block_node if instance_variable_defined?(:@example_block_node)
|
113
113
|
|
114
|
-
@example_block_node =
|
114
|
+
@example_block_node = node.each_ancestor_node.find do |node|
|
115
115
|
next false unless node.block_type?
|
116
116
|
send_node = node.children.first
|
117
117
|
receiver_node, method_name, = *send_node
|
@@ -157,7 +157,7 @@ module Transpec
|
|
157
157
|
syntax << ' ... }'
|
158
158
|
end
|
159
159
|
|
160
|
-
|
160
|
+
report.records << Record.new(original_syntax, converted_syntax)
|
161
161
|
end
|
162
162
|
|
163
163
|
class OnelinerShouldHaveRecord < Have::HaveRecord
|
@@ -19,12 +19,12 @@ module Transpec
|
|
19
19
|
false
|
20
20
|
end
|
21
21
|
|
22
|
-
def self.
|
22
|
+
def self.check_target_node_statically(node)
|
23
23
|
node = node.parent_node if node == BE_NODE
|
24
|
+
return false unless node && node.send_type?
|
24
25
|
receiver_node, method_name, *_ = *node
|
25
26
|
return false if receiver_node.nil?
|
26
|
-
|
27
|
-
check_target_node_dynamically(node, runtime_data)
|
27
|
+
OPERATORS.include?(method_name)
|
28
28
|
end
|
29
29
|
|
30
30
|
define_dynamic_analysis_request do |rewriter|
|
@@ -94,10 +94,12 @@ module Transpec
|
|
94
94
|
|
95
95
|
# Need to register record after all source rewrites are done
|
96
96
|
# to avoid false record when failed with overlapped rewrite.
|
97
|
+
accurate = !arg_is_enumerable?.nil?
|
98
|
+
|
97
99
|
if arg_is_enumerable?
|
98
|
-
register_record('=~ [1, 2]', 'match_array([1, 2])')
|
100
|
+
register_record('=~ [1, 2]', 'match_array([1, 2])', accurate)
|
99
101
|
else
|
100
|
-
register_record('=~ /pattern/', 'match(/pattern/)')
|
102
|
+
register_record('=~ /pattern/', 'match(/pattern/)', accurate)
|
101
103
|
end
|
102
104
|
end
|
103
105
|
|
@@ -110,9 +112,14 @@ module Transpec
|
|
110
112
|
end
|
111
113
|
|
112
114
|
def arg_is_enumerable?
|
113
|
-
|
114
|
-
|
115
|
-
|
115
|
+
case arg_node.type
|
116
|
+
when :array
|
117
|
+
true
|
118
|
+
when :regexp
|
119
|
+
false
|
120
|
+
else
|
121
|
+
runtime_data[arg_node, :arg_is_enumerable?]
|
122
|
+
end
|
116
123
|
end
|
117
124
|
|
118
125
|
def parenthesize_single_line!(always)
|
@@ -128,7 +135,7 @@ module Transpec
|
|
128
135
|
|
129
136
|
def parenthesize_multi_line!(linefeed)
|
130
137
|
insert_before(range_in_between_selector_and_arg, '(')
|
131
|
-
matcher_line_indentation = indentation_of_line(
|
138
|
+
matcher_line_indentation = indentation_of_line(node)
|
132
139
|
right_parenthesis = "#{linefeed}#{matcher_line_indentation})"
|
133
140
|
insert_after(expression_range, right_parenthesis)
|
134
141
|
end
|
@@ -150,9 +157,18 @@ module Transpec
|
|
150
157
|
end
|
151
158
|
end
|
152
159
|
|
153
|
-
def
|
160
|
+
def matcher_range
|
161
|
+
if be_node
|
162
|
+
expression_range
|
163
|
+
else
|
164
|
+
selector_range.join(expression_range.end)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def register_record(original_syntax, converted_syntax, accurate = true)
|
154
169
|
original_syntax ||= "#{method_name} expected"
|
155
|
-
|
170
|
+
annotation = AccuracyAnnotation.new(matcher_range) unless accurate
|
171
|
+
report.records << Record.new(original_syntax, converted_syntax, annotation)
|
156
172
|
end
|
157
173
|
end
|
158
174
|
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'transpec/syntax'
|
4
|
+
require 'transpec/syntax/mixin/send'
|
5
|
+
require 'transpec/util'
|
6
|
+
|
7
|
+
module Transpec
|
8
|
+
class Syntax
|
9
|
+
class Pending < Syntax
|
10
|
+
include Mixin::Send, Util
|
11
|
+
|
12
|
+
def self.conversion_target_node?(node, runtime_data = nil)
|
13
|
+
return false unless target_node?(node, runtime_data)
|
14
|
+
|
15
|
+
# Check whether the context is example group to differenciate
|
16
|
+
# RSpec::Core::ExampleGroup.pending (a relative of #it) and
|
17
|
+
# RSpec::Core::ExampleGroup#pending (marks the example as pending in #it block).
|
18
|
+
if runtime_data && runtime_data.run?(node)
|
19
|
+
# If we have runtime data, check with it.
|
20
|
+
runtime_data[node, :example_context?]
|
21
|
+
else
|
22
|
+
# Otherwise check statically.
|
23
|
+
inspector = StaticContextInspector.new(node)
|
24
|
+
inspector.scopes.last == :example
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.target_method?(receiver_node, method_name)
|
29
|
+
receiver_node.nil? && method_name == :pending
|
30
|
+
end
|
31
|
+
|
32
|
+
define_dynamic_analysis_request do |rewriter|
|
33
|
+
code = 'is_a?(RSpec::Core::ExampleGroup)'
|
34
|
+
rewriter.register_request(node, :example_context?, code, :context)
|
35
|
+
end
|
36
|
+
|
37
|
+
def convert_deprecated_syntax!
|
38
|
+
if block_node
|
39
|
+
unblock!
|
40
|
+
else
|
41
|
+
convert_to_skip!
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def convert_to_skip!
|
48
|
+
replace(selector_range, 'skip')
|
49
|
+
register_record('pending', 'skip')
|
50
|
+
end
|
51
|
+
|
52
|
+
def unblock!
|
53
|
+
if block_beginning_line == block_body_line
|
54
|
+
range_between_pending_and_body =
|
55
|
+
expression_range.end.join(block_body_node.loc.expression.begin)
|
56
|
+
replace(range_between_pending_and_body, "\n" + indentation_of_line(node))
|
57
|
+
else
|
58
|
+
remove(expression_range.end.join(block_node.loc.begin))
|
59
|
+
outdent!(block_body_node, node)
|
60
|
+
end
|
61
|
+
|
62
|
+
if block_body_line == block_end_line
|
63
|
+
remove(block_body_node.loc.expression.end.join(block_node.loc.end))
|
64
|
+
else
|
65
|
+
remove(line_range(block_node.loc.end))
|
66
|
+
end
|
67
|
+
|
68
|
+
register_record('pending { do_something_fail }', 'pending; do_something_fail')
|
69
|
+
end
|
70
|
+
|
71
|
+
def outdent!(target_node, base_node)
|
72
|
+
indentation_width = indentation_width(target_node, base_node)
|
73
|
+
|
74
|
+
return unless indentation_width > 0
|
75
|
+
|
76
|
+
each_line_range(target_node) do |line_range|
|
77
|
+
remove(line_range.resize(indentation_width))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def indentation_width(target, base)
|
82
|
+
indentation_of_line(target).size - indentation_of_line(base).size
|
83
|
+
end
|
84
|
+
|
85
|
+
def block_node
|
86
|
+
block_node_taken_by_method(node)
|
87
|
+
end
|
88
|
+
|
89
|
+
def block_body_node
|
90
|
+
block_node.children[2]
|
91
|
+
end
|
92
|
+
|
93
|
+
def block_beginning_line
|
94
|
+
block_node.loc.begin.line
|
95
|
+
end
|
96
|
+
|
97
|
+
def block_body_line
|
98
|
+
block_body_node.loc.expression.line
|
99
|
+
end
|
100
|
+
|
101
|
+
def block_end_line
|
102
|
+
block_node.loc.end.line
|
103
|
+
end
|
104
|
+
|
105
|
+
def register_record(original_syntax, converted_syntax)
|
106
|
+
report.records << Record.new(original_syntax, converted_syntax)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -17,22 +17,22 @@ module Transpec
|
|
17
17
|
def remove_useless_and_return!
|
18
18
|
removed = super
|
19
19
|
return unless removed
|
20
|
-
|
20
|
+
report.records << ReceiveUselessAndReturnRecord.new(self)
|
21
21
|
end
|
22
22
|
|
23
23
|
def add_receiver_arg_to_any_instance_implementation_block!
|
24
24
|
added = super
|
25
25
|
return unless added
|
26
|
-
|
26
|
+
report.records << ReceiveAnyInstanceBlockRecord.new(self)
|
27
27
|
end
|
28
28
|
|
29
29
|
def any_instance?
|
30
|
-
|
30
|
+
expectation.any_instance?
|
31
31
|
end
|
32
32
|
|
33
33
|
def any_instance_block_node
|
34
34
|
return unless any_instance?
|
35
|
-
super ||
|
35
|
+
super || expectation.block_node
|
36
36
|
end
|
37
37
|
|
38
38
|
class ReceiveAnyInstanceBlockRecord < AnyInstanceBlockRecord
|
@@ -9,7 +9,7 @@ module Transpec
|
|
9
9
|
class Framework
|
10
10
|
include Util, ::AST::Sexp
|
11
11
|
|
12
|
-
attr_reader :rspec_configure
|
12
|
+
attr_reader :rspec_configure, :source_rewriter
|
13
13
|
|
14
14
|
def initialize(rspec_configure, source_rewriter)
|
15
15
|
@rspec_configure = rspec_configure
|
@@ -27,7 +27,7 @@ module Transpec
|
|
27
27
|
|
28
28
|
if setter_node
|
29
29
|
arg_node = setter_node.children[2]
|
30
|
-
|
30
|
+
source_rewriter.replace(arg_node.loc.expression, value.to_s)
|
31
31
|
else
|
32
32
|
add_configuration!(config_name, value)
|
33
33
|
end
|
@@ -77,7 +77,7 @@ module Transpec
|
|
77
77
|
lines.map! { |line| line + "\n" }
|
78
78
|
|
79
79
|
insertion_position = beginning_of_line_range(block_node_to_insert_code.loc.end)
|
80
|
-
|
80
|
+
source_rewriter.insert_before(insertion_position, lines.join(''))
|
81
81
|
end
|
82
82
|
|
83
83
|
def config_variable_name
|
@@ -35,7 +35,7 @@ module Transpec
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def expectize!(negative_form = 'not_to', parenthesize_matcher_arg = true)
|
38
|
-
fail ContextError.new(
|
38
|
+
fail ContextError.new("##{method_name}", '#expect', selector_range) unless expect_available?
|
39
39
|
|
40
40
|
if proc_literal?(subject_node)
|
41
41
|
replace(range_of_subject_method_taking_block, 'expect')
|
@@ -74,7 +74,7 @@ module Transpec
|
|
74
74
|
converted_syntax << negative_form_of_to
|
75
75
|
end
|
76
76
|
|
77
|
-
|
77
|
+
report.records << Record.new(original_syntax, converted_syntax)
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
@@ -45,7 +45,7 @@ module Transpec
|
|
45
45
|
|
46
46
|
def expectize!(negative_form = 'not_to')
|
47
47
|
unless expect_to_receive_available?
|
48
|
-
fail ContextError.new(
|
48
|
+
fail ContextError.new("##{method_name}", '#expect', selector_range)
|
49
49
|
end
|
50
50
|
|
51
51
|
convert_to_syntax!('expect', negative_form)
|
@@ -56,7 +56,7 @@ module Transpec
|
|
56
56
|
return unless useless_expectation?
|
57
57
|
|
58
58
|
unless allow_to_receive_available?
|
59
|
-
fail ContextError.new(
|
59
|
+
fail ContextError.new("##{method_name}", '#allow', selector_range)
|
60
60
|
end
|
61
61
|
|
62
62
|
convert_to_syntax!('allow', negative_form)
|
@@ -157,7 +157,7 @@ module Transpec
|
|
157
157
|
end
|
158
158
|
|
159
159
|
def register_record(record_class, negative_form_of_to = nil)
|
160
|
-
|
160
|
+
report.records << record_class.new(self, negative_form_of_to)
|
161
161
|
end
|
162
162
|
|
163
163
|
class ExpectBaseRecord < Record
|
data/lib/transpec/util.rb
CHANGED
@@ -12,6 +12,14 @@ module Transpec
|
|
12
12
|
|
13
13
|
module_function
|
14
14
|
|
15
|
+
def node_id(node)
|
16
|
+
source_range = node.loc.expression
|
17
|
+
source_buffer = source_range.source_buffer
|
18
|
+
absolute_path = File.expand_path(source_buffer.name)
|
19
|
+
relative_path = Pathname.new(absolute_path).relative_path_from(Pathname.pwd).to_s
|
20
|
+
[relative_path, source_range.begin_pos, source_range.end_pos].join('_')
|
21
|
+
end
|
22
|
+
|
15
23
|
def proc_literal?(node)
|
16
24
|
return false unless node.block_type?
|
17
25
|
|
@@ -133,16 +141,40 @@ module Transpec
|
|
133
141
|
end
|
134
142
|
|
135
143
|
def beginning_of_line_range(arg)
|
136
|
-
range =
|
137
|
-
when AST::Node then arg.loc.expression
|
138
|
-
when Parser::Source::Range then arg
|
139
|
-
else fail ArgumentError, "Invalid argument #{arg}"
|
140
|
-
end
|
141
|
-
|
144
|
+
range = range_from_arg(arg)
|
142
145
|
begin_pos = range.begin_pos - range.column
|
143
146
|
Parser::Source::Range.new(range.source_buffer, begin_pos, begin_pos)
|
144
147
|
end
|
145
148
|
|
149
|
+
def end_of_line_range(arg)
|
150
|
+
range = range_from_arg(arg)
|
151
|
+
begin_pos = beginning_of_line_range(range).begin_pos + range.source_line.size
|
152
|
+
Parser::Source::Range.new(range.source_buffer, begin_pos, begin_pos)
|
153
|
+
end
|
154
|
+
|
155
|
+
def line_range(arg)
|
156
|
+
range = range_from_arg(arg)
|
157
|
+
beginning_of_line_range(range).resize(range.source_line.size + 1)
|
158
|
+
end
|
159
|
+
|
160
|
+
def each_line_range(arg)
|
161
|
+
multiline_range = range_from_arg(arg)
|
162
|
+
range = line_range(multiline_range)
|
163
|
+
|
164
|
+
while range.line <= multiline_range.end.line
|
165
|
+
yield range
|
166
|
+
range = line_range(range.end)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def range_from_arg(arg)
|
171
|
+
case arg
|
172
|
+
when AST::Node then arg.loc.expression
|
173
|
+
when Parser::Source::Range then arg
|
174
|
+
else fail ArgumentError, "Invalid argument #{arg}"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
146
178
|
def literal?(node)
|
147
179
|
case node.type
|
148
180
|
when *LITERAL_TYPES
|