prism 0.14.0 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -1
- data/README.md +1 -1
- data/config.yml +86 -21
- data/ext/prism/api_node.c +213 -67
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +133 -83
- data/include/prism/diagnostic.h +1 -0
- data/include/prism/node.h +7 -0
- data/include/prism/util/pm_constant_pool.h +20 -6
- data/include/prism/version.h +2 -2
- data/include/prism.h +1 -1
- data/lib/prism/compiler.rb +9 -0
- data/lib/prism/debug.rb +30 -26
- data/lib/prism/dispatcher.rb +42 -0
- data/lib/prism/dsl.rb +23 -8
- data/lib/prism/ffi.rb +2 -2
- data/lib/prism/lex_compat.rb +9 -9
- data/lib/prism/mutation_compiler.rb +18 -3
- data/lib/prism/node.rb +580 -120
- data/lib/prism/serialize.rb +83 -77
- data/lib/prism/visitor.rb +9 -0
- data/prism.gemspec +1 -1
- data/src/diagnostic.c +1 -0
- data/src/node.c +99 -18
- data/src/prettyprint.c +102 -45
- data/src/prism.c +288 -88
- data/src/serialize.c +95 -57
- data/src/util/pm_constant_pool.c +25 -11
- metadata +2 -2
data/lib/prism/node.rb
CHANGED
@@ -1018,8 +1018,12 @@ module Prism
|
|
1018
1018
|
# $'
|
1019
1019
|
# ^^
|
1020
1020
|
class BackReferenceReadNode < Node
|
1021
|
-
#
|
1022
|
-
|
1021
|
+
# attr_reader name: Symbol
|
1022
|
+
attr_reader :name
|
1023
|
+
|
1024
|
+
# def initialize: (name: Symbol, location: Location) -> void
|
1025
|
+
def initialize(name, location)
|
1026
|
+
@name = name
|
1023
1027
|
@location = location
|
1024
1028
|
end
|
1025
1029
|
|
@@ -1046,6 +1050,7 @@ module Prism
|
|
1046
1050
|
# def copy: (**params) -> BackReferenceReadNode
|
1047
1051
|
def copy(**params)
|
1048
1052
|
BackReferenceReadNode.new(
|
1053
|
+
params.fetch(:name) { name },
|
1049
1054
|
params.fetch(:location) { location },
|
1050
1055
|
)
|
1051
1056
|
end
|
@@ -1055,11 +1060,12 @@ module Prism
|
|
1055
1060
|
|
1056
1061
|
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
|
1057
1062
|
def deconstruct_keys(keys)
|
1058
|
-
{ location: location }
|
1063
|
+
{ name: name, location: location }
|
1059
1064
|
end
|
1060
1065
|
|
1061
1066
|
def inspect(inspector = NodeInspector.new)
|
1062
1067
|
inspector << inspector.header(self)
|
1068
|
+
inspector << "└── name: #{name.inspect}\n"
|
1063
1069
|
inspector.to_str
|
1064
1070
|
end
|
1065
1071
|
|
@@ -1913,15 +1919,6 @@ module Prism
|
|
1913
1919
|
# attr_reader message_loc: Location?
|
1914
1920
|
attr_reader :message_loc
|
1915
1921
|
|
1916
|
-
# attr_reader opening_loc: Location?
|
1917
|
-
attr_reader :opening_loc
|
1918
|
-
|
1919
|
-
# attr_reader arguments: ArgumentsNode?
|
1920
|
-
attr_reader :arguments
|
1921
|
-
|
1922
|
-
# attr_reader closing_loc: Location?
|
1923
|
-
attr_reader :closing_loc
|
1924
|
-
|
1925
1922
|
# attr_reader flags: Integer
|
1926
1923
|
private attr_reader :flags
|
1927
1924
|
|
@@ -1937,14 +1934,11 @@ module Prism
|
|
1937
1934
|
# attr_reader value: Node
|
1938
1935
|
attr_reader :value
|
1939
1936
|
|
1940
|
-
# def initialize: (receiver: Node?, call_operator_loc: Location?, message_loc: Location?,
|
1941
|
-
def initialize(receiver, call_operator_loc, message_loc,
|
1937
|
+
# def initialize: (receiver: Node?, call_operator_loc: Location?, message_loc: Location?, flags: Integer, read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node, location: Location) -> void
|
1938
|
+
def initialize(receiver, call_operator_loc, message_loc, flags, read_name, write_name, operator_loc, value, location)
|
1942
1939
|
@receiver = receiver
|
1943
1940
|
@call_operator_loc = call_operator_loc
|
1944
1941
|
@message_loc = message_loc
|
1945
|
-
@opening_loc = opening_loc
|
1946
|
-
@arguments = arguments
|
1947
|
-
@closing_loc = closing_loc
|
1948
1942
|
@flags = flags
|
1949
1943
|
@read_name = read_name
|
1950
1944
|
@write_name = write_name
|
@@ -1960,21 +1954,20 @@ module Prism
|
|
1960
1954
|
|
1961
1955
|
# def child_nodes: () -> Array[nil | Node]
|
1962
1956
|
def child_nodes
|
1963
|
-
[receiver,
|
1957
|
+
[receiver, value]
|
1964
1958
|
end
|
1965
1959
|
|
1966
1960
|
# def compact_child_nodes: () -> Array[Node]
|
1967
1961
|
def compact_child_nodes
|
1968
1962
|
compact = []
|
1969
1963
|
compact << receiver if receiver
|
1970
|
-
compact << arguments if arguments
|
1971
1964
|
compact << value
|
1972
1965
|
compact
|
1973
1966
|
end
|
1974
1967
|
|
1975
1968
|
# def comment_targets: () -> Array[Node | Location]
|
1976
1969
|
def comment_targets
|
1977
|
-
[*receiver, *call_operator_loc, *message_loc,
|
1970
|
+
[*receiver, *call_operator_loc, *message_loc, operator_loc, value]
|
1978
1971
|
end
|
1979
1972
|
|
1980
1973
|
# def copy: (**params) -> CallAndWriteNode
|
@@ -1983,9 +1976,6 @@ module Prism
|
|
1983
1976
|
params.fetch(:receiver) { receiver },
|
1984
1977
|
params.fetch(:call_operator_loc) { call_operator_loc },
|
1985
1978
|
params.fetch(:message_loc) { message_loc },
|
1986
|
-
params.fetch(:opening_loc) { opening_loc },
|
1987
|
-
params.fetch(:arguments) { arguments },
|
1988
|
-
params.fetch(:closing_loc) { closing_loc },
|
1989
1979
|
params.fetch(:flags) { flags },
|
1990
1980
|
params.fetch(:read_name) { read_name },
|
1991
1981
|
params.fetch(:write_name) { write_name },
|
@@ -2000,7 +1990,7 @@ module Prism
|
|
2000
1990
|
|
2001
1991
|
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
|
2002
1992
|
def deconstruct_keys(keys)
|
2003
|
-
{ receiver: receiver, call_operator_loc: call_operator_loc, message_loc: message_loc,
|
1993
|
+
{ receiver: receiver, call_operator_loc: call_operator_loc, message_loc: message_loc, flags: flags, read_name: read_name, write_name: write_name, operator_loc: operator_loc, value: value, location: location }
|
2004
1994
|
end
|
2005
1995
|
|
2006
1996
|
# def call_operator: () -> String?
|
@@ -2013,16 +2003,6 @@ module Prism
|
|
2013
2003
|
message_loc&.slice
|
2014
2004
|
end
|
2015
2005
|
|
2016
|
-
# def opening: () -> String?
|
2017
|
-
def opening
|
2018
|
-
opening_loc&.slice
|
2019
|
-
end
|
2020
|
-
|
2021
|
-
# def closing: () -> String?
|
2022
|
-
def closing
|
2023
|
-
closing_loc&.slice
|
2024
|
-
end
|
2025
|
-
|
2026
2006
|
# def safe_navigation?: () -> bool
|
2027
2007
|
def safe_navigation?
|
2028
2008
|
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
|
@@ -2048,14 +2028,6 @@ module Prism
|
|
2048
2028
|
end
|
2049
2029
|
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
|
2050
2030
|
inspector << "├── message_loc: #{inspector.location(message_loc)}\n"
|
2051
|
-
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
|
2052
|
-
if (arguments = self.arguments).nil?
|
2053
|
-
inspector << "├── arguments: ∅\n"
|
2054
|
-
else
|
2055
|
-
inspector << "├── arguments:\n"
|
2056
|
-
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
|
2057
|
-
end
|
2058
|
-
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
|
2059
2031
|
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?)].compact
|
2060
2032
|
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
|
2061
2033
|
inspector << "├── read_name: #{read_name.inspect}\n"
|
@@ -2307,15 +2279,6 @@ module Prism
|
|
2307
2279
|
# attr_reader message_loc: Location?
|
2308
2280
|
attr_reader :message_loc
|
2309
2281
|
|
2310
|
-
# attr_reader opening_loc: Location?
|
2311
|
-
attr_reader :opening_loc
|
2312
|
-
|
2313
|
-
# attr_reader arguments: ArgumentsNode?
|
2314
|
-
attr_reader :arguments
|
2315
|
-
|
2316
|
-
# attr_reader closing_loc: Location?
|
2317
|
-
attr_reader :closing_loc
|
2318
|
-
|
2319
2282
|
# attr_reader flags: Integer
|
2320
2283
|
private attr_reader :flags
|
2321
2284
|
|
@@ -2334,14 +2297,11 @@ module Prism
|
|
2334
2297
|
# attr_reader value: Node
|
2335
2298
|
attr_reader :value
|
2336
2299
|
|
2337
|
-
# def initialize: (receiver: Node?, call_operator_loc: Location?, message_loc: Location?,
|
2338
|
-
def initialize(receiver, call_operator_loc, message_loc,
|
2300
|
+
# def initialize: (receiver: Node?, call_operator_loc: Location?, message_loc: Location?, flags: Integer, read_name: Symbol, write_name: Symbol, operator: Symbol, operator_loc: Location, value: Node, location: Location) -> void
|
2301
|
+
def initialize(receiver, call_operator_loc, message_loc, flags, read_name, write_name, operator, operator_loc, value, location)
|
2339
2302
|
@receiver = receiver
|
2340
2303
|
@call_operator_loc = call_operator_loc
|
2341
2304
|
@message_loc = message_loc
|
2342
|
-
@opening_loc = opening_loc
|
2343
|
-
@arguments = arguments
|
2344
|
-
@closing_loc = closing_loc
|
2345
2305
|
@flags = flags
|
2346
2306
|
@read_name = read_name
|
2347
2307
|
@write_name = write_name
|
@@ -2358,21 +2318,20 @@ module Prism
|
|
2358
2318
|
|
2359
2319
|
# def child_nodes: () -> Array[nil | Node]
|
2360
2320
|
def child_nodes
|
2361
|
-
[receiver,
|
2321
|
+
[receiver, value]
|
2362
2322
|
end
|
2363
2323
|
|
2364
2324
|
# def compact_child_nodes: () -> Array[Node]
|
2365
2325
|
def compact_child_nodes
|
2366
2326
|
compact = []
|
2367
2327
|
compact << receiver if receiver
|
2368
|
-
compact << arguments if arguments
|
2369
2328
|
compact << value
|
2370
2329
|
compact
|
2371
2330
|
end
|
2372
2331
|
|
2373
2332
|
# def comment_targets: () -> Array[Node | Location]
|
2374
2333
|
def comment_targets
|
2375
|
-
[*receiver, *call_operator_loc, *message_loc,
|
2334
|
+
[*receiver, *call_operator_loc, *message_loc, operator_loc, value]
|
2376
2335
|
end
|
2377
2336
|
|
2378
2337
|
# def copy: (**params) -> CallOperatorWriteNode
|
@@ -2381,9 +2340,6 @@ module Prism
|
|
2381
2340
|
params.fetch(:receiver) { receiver },
|
2382
2341
|
params.fetch(:call_operator_loc) { call_operator_loc },
|
2383
2342
|
params.fetch(:message_loc) { message_loc },
|
2384
|
-
params.fetch(:opening_loc) { opening_loc },
|
2385
|
-
params.fetch(:arguments) { arguments },
|
2386
|
-
params.fetch(:closing_loc) { closing_loc },
|
2387
2343
|
params.fetch(:flags) { flags },
|
2388
2344
|
params.fetch(:read_name) { read_name },
|
2389
2345
|
params.fetch(:write_name) { write_name },
|
@@ -2399,7 +2355,7 @@ module Prism
|
|
2399
2355
|
|
2400
2356
|
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
|
2401
2357
|
def deconstruct_keys(keys)
|
2402
|
-
{ receiver: receiver, call_operator_loc: call_operator_loc, message_loc: message_loc,
|
2358
|
+
{ receiver: receiver, call_operator_loc: call_operator_loc, message_loc: message_loc, flags: flags, read_name: read_name, write_name: write_name, operator: operator, operator_loc: operator_loc, value: value, location: location }
|
2403
2359
|
end
|
2404
2360
|
|
2405
2361
|
# def call_operator: () -> String?
|
@@ -2412,16 +2368,6 @@ module Prism
|
|
2412
2368
|
message_loc&.slice
|
2413
2369
|
end
|
2414
2370
|
|
2415
|
-
# def opening: () -> String?
|
2416
|
-
def opening
|
2417
|
-
opening_loc&.slice
|
2418
|
-
end
|
2419
|
-
|
2420
|
-
# def closing: () -> String?
|
2421
|
-
def closing
|
2422
|
-
closing_loc&.slice
|
2423
|
-
end
|
2424
|
-
|
2425
2371
|
# def safe_navigation?: () -> bool
|
2426
2372
|
def safe_navigation?
|
2427
2373
|
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
|
@@ -2442,14 +2388,6 @@ module Prism
|
|
2442
2388
|
end
|
2443
2389
|
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
|
2444
2390
|
inspector << "├── message_loc: #{inspector.location(message_loc)}\n"
|
2445
|
-
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
|
2446
|
-
if (arguments = self.arguments).nil?
|
2447
|
-
inspector << "├── arguments: ∅\n"
|
2448
|
-
else
|
2449
|
-
inspector << "├── arguments:\n"
|
2450
|
-
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
|
2451
|
-
end
|
2452
|
-
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
|
2453
2391
|
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?)].compact
|
2454
2392
|
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
|
2455
2393
|
inspector << "├── read_name: #{read_name.inspect}\n"
|
@@ -2504,15 +2442,6 @@ module Prism
|
|
2504
2442
|
# attr_reader message_loc: Location?
|
2505
2443
|
attr_reader :message_loc
|
2506
2444
|
|
2507
|
-
# attr_reader opening_loc: Location?
|
2508
|
-
attr_reader :opening_loc
|
2509
|
-
|
2510
|
-
# attr_reader arguments: ArgumentsNode?
|
2511
|
-
attr_reader :arguments
|
2512
|
-
|
2513
|
-
# attr_reader closing_loc: Location?
|
2514
|
-
attr_reader :closing_loc
|
2515
|
-
|
2516
2445
|
# attr_reader flags: Integer
|
2517
2446
|
private attr_reader :flags
|
2518
2447
|
|
@@ -2528,14 +2457,11 @@ module Prism
|
|
2528
2457
|
# attr_reader value: Node
|
2529
2458
|
attr_reader :value
|
2530
2459
|
|
2531
|
-
# def initialize: (receiver: Node?, call_operator_loc: Location?, message_loc: Location?,
|
2532
|
-
def initialize(receiver, call_operator_loc, message_loc,
|
2460
|
+
# def initialize: (receiver: Node?, call_operator_loc: Location?, message_loc: Location?, flags: Integer, read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node, location: Location) -> void
|
2461
|
+
def initialize(receiver, call_operator_loc, message_loc, flags, read_name, write_name, operator_loc, value, location)
|
2533
2462
|
@receiver = receiver
|
2534
2463
|
@call_operator_loc = call_operator_loc
|
2535
2464
|
@message_loc = message_loc
|
2536
|
-
@opening_loc = opening_loc
|
2537
|
-
@arguments = arguments
|
2538
|
-
@closing_loc = closing_loc
|
2539
2465
|
@flags = flags
|
2540
2466
|
@read_name = read_name
|
2541
2467
|
@write_name = write_name
|
@@ -2551,21 +2477,20 @@ module Prism
|
|
2551
2477
|
|
2552
2478
|
# def child_nodes: () -> Array[nil | Node]
|
2553
2479
|
def child_nodes
|
2554
|
-
[receiver,
|
2480
|
+
[receiver, value]
|
2555
2481
|
end
|
2556
2482
|
|
2557
2483
|
# def compact_child_nodes: () -> Array[Node]
|
2558
2484
|
def compact_child_nodes
|
2559
2485
|
compact = []
|
2560
2486
|
compact << receiver if receiver
|
2561
|
-
compact << arguments if arguments
|
2562
2487
|
compact << value
|
2563
2488
|
compact
|
2564
2489
|
end
|
2565
2490
|
|
2566
2491
|
# def comment_targets: () -> Array[Node | Location]
|
2567
2492
|
def comment_targets
|
2568
|
-
[*receiver, *call_operator_loc, *message_loc,
|
2493
|
+
[*receiver, *call_operator_loc, *message_loc, operator_loc, value]
|
2569
2494
|
end
|
2570
2495
|
|
2571
2496
|
# def copy: (**params) -> CallOrWriteNode
|
@@ -2574,9 +2499,6 @@ module Prism
|
|
2574
2499
|
params.fetch(:receiver) { receiver },
|
2575
2500
|
params.fetch(:call_operator_loc) { call_operator_loc },
|
2576
2501
|
params.fetch(:message_loc) { message_loc },
|
2577
|
-
params.fetch(:opening_loc) { opening_loc },
|
2578
|
-
params.fetch(:arguments) { arguments },
|
2579
|
-
params.fetch(:closing_loc) { closing_loc },
|
2580
2502
|
params.fetch(:flags) { flags },
|
2581
2503
|
params.fetch(:read_name) { read_name },
|
2582
2504
|
params.fetch(:write_name) { write_name },
|
@@ -2591,7 +2513,7 @@ module Prism
|
|
2591
2513
|
|
2592
2514
|
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
|
2593
2515
|
def deconstruct_keys(keys)
|
2594
|
-
{ receiver: receiver, call_operator_loc: call_operator_loc, message_loc: message_loc,
|
2516
|
+
{ receiver: receiver, call_operator_loc: call_operator_loc, message_loc: message_loc, flags: flags, read_name: read_name, write_name: write_name, operator_loc: operator_loc, value: value, location: location }
|
2595
2517
|
end
|
2596
2518
|
|
2597
2519
|
# def call_operator: () -> String?
|
@@ -2604,16 +2526,6 @@ module Prism
|
|
2604
2526
|
message_loc&.slice
|
2605
2527
|
end
|
2606
2528
|
|
2607
|
-
# def opening: () -> String?
|
2608
|
-
def opening
|
2609
|
-
opening_loc&.slice
|
2610
|
-
end
|
2611
|
-
|
2612
|
-
# def closing: () -> String?
|
2613
|
-
def closing
|
2614
|
-
closing_loc&.slice
|
2615
|
-
end
|
2616
|
-
|
2617
2529
|
# def safe_navigation?: () -> bool
|
2618
2530
|
def safe_navigation?
|
2619
2531
|
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
|
@@ -2639,14 +2551,6 @@ module Prism
|
|
2639
2551
|
end
|
2640
2552
|
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
|
2641
2553
|
inspector << "├── message_loc: #{inspector.location(message_loc)}\n"
|
2642
|
-
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
|
2643
|
-
if (arguments = self.arguments).nil?
|
2644
|
-
inspector << "├── arguments: ∅\n"
|
2645
|
-
else
|
2646
|
-
inspector << "├── arguments:\n"
|
2647
|
-
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
|
2648
|
-
end
|
2649
|
-
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
|
2650
2554
|
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?)].compact
|
2651
2555
|
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
|
2652
2556
|
inspector << "├── read_name: #{read_name.inspect}\n"
|
@@ -7826,6 +7730,562 @@ module Prism
|
|
7826
7730
|
end
|
7827
7731
|
end
|
7828
7732
|
|
7733
|
+
# Represents the use of the `&&=` operator on a call to the `[]` method.
|
7734
|
+
#
|
7735
|
+
# foo.bar[baz] &&= value
|
7736
|
+
# ^^^^^^^^^^^^^^^^^^^^^^
|
7737
|
+
class IndexAndWriteNode < Node
|
7738
|
+
# attr_reader receiver: Node?
|
7739
|
+
attr_reader :receiver
|
7740
|
+
|
7741
|
+
# attr_reader call_operator_loc: Location?
|
7742
|
+
attr_reader :call_operator_loc
|
7743
|
+
|
7744
|
+
# attr_reader opening_loc: Location
|
7745
|
+
attr_reader :opening_loc
|
7746
|
+
|
7747
|
+
# attr_reader arguments: ArgumentsNode?
|
7748
|
+
attr_reader :arguments
|
7749
|
+
|
7750
|
+
# attr_reader closing_loc: Location
|
7751
|
+
attr_reader :closing_loc
|
7752
|
+
|
7753
|
+
# attr_reader block: Node?
|
7754
|
+
attr_reader :block
|
7755
|
+
|
7756
|
+
# attr_reader flags: Integer
|
7757
|
+
private attr_reader :flags
|
7758
|
+
|
7759
|
+
# attr_reader operator_loc: Location
|
7760
|
+
attr_reader :operator_loc
|
7761
|
+
|
7762
|
+
# attr_reader value: Node
|
7763
|
+
attr_reader :value
|
7764
|
+
|
7765
|
+
# def initialize: (receiver: Node?, call_operator_loc: Location?, opening_loc: Location, arguments: ArgumentsNode?, closing_loc: Location, block: Node?, flags: Integer, operator_loc: Location, value: Node, location: Location) -> void
|
7766
|
+
def initialize(receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, flags, operator_loc, value, location)
|
7767
|
+
@receiver = receiver
|
7768
|
+
@call_operator_loc = call_operator_loc
|
7769
|
+
@opening_loc = opening_loc
|
7770
|
+
@arguments = arguments
|
7771
|
+
@closing_loc = closing_loc
|
7772
|
+
@block = block
|
7773
|
+
@flags = flags
|
7774
|
+
@operator_loc = operator_loc
|
7775
|
+
@value = value
|
7776
|
+
@location = location
|
7777
|
+
end
|
7778
|
+
|
7779
|
+
# def accept: (visitor: Visitor) -> void
|
7780
|
+
def accept(visitor)
|
7781
|
+
visitor.visit_index_and_write_node(self)
|
7782
|
+
end
|
7783
|
+
|
7784
|
+
# def child_nodes: () -> Array[nil | Node]
|
7785
|
+
def child_nodes
|
7786
|
+
[receiver, arguments, block, value]
|
7787
|
+
end
|
7788
|
+
|
7789
|
+
# def compact_child_nodes: () -> Array[Node]
|
7790
|
+
def compact_child_nodes
|
7791
|
+
compact = []
|
7792
|
+
compact << receiver if receiver
|
7793
|
+
compact << arguments if arguments
|
7794
|
+
compact << block if block
|
7795
|
+
compact << value
|
7796
|
+
compact
|
7797
|
+
end
|
7798
|
+
|
7799
|
+
# def comment_targets: () -> Array[Node | Location]
|
7800
|
+
def comment_targets
|
7801
|
+
[*receiver, *call_operator_loc, opening_loc, *arguments, closing_loc, *block, operator_loc, value]
|
7802
|
+
end
|
7803
|
+
|
7804
|
+
# def copy: (**params) -> IndexAndWriteNode
|
7805
|
+
def copy(**params)
|
7806
|
+
IndexAndWriteNode.new(
|
7807
|
+
params.fetch(:receiver) { receiver },
|
7808
|
+
params.fetch(:call_operator_loc) { call_operator_loc },
|
7809
|
+
params.fetch(:opening_loc) { opening_loc },
|
7810
|
+
params.fetch(:arguments) { arguments },
|
7811
|
+
params.fetch(:closing_loc) { closing_loc },
|
7812
|
+
params.fetch(:block) { block },
|
7813
|
+
params.fetch(:flags) { flags },
|
7814
|
+
params.fetch(:operator_loc) { operator_loc },
|
7815
|
+
params.fetch(:value) { value },
|
7816
|
+
params.fetch(:location) { location },
|
7817
|
+
)
|
7818
|
+
end
|
7819
|
+
|
7820
|
+
# def deconstruct: () -> Array[nil | Node]
|
7821
|
+
alias deconstruct child_nodes
|
7822
|
+
|
7823
|
+
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
|
7824
|
+
def deconstruct_keys(keys)
|
7825
|
+
{ receiver: receiver, call_operator_loc: call_operator_loc, opening_loc: opening_loc, arguments: arguments, closing_loc: closing_loc, block: block, flags: flags, operator_loc: operator_loc, value: value, location: location }
|
7826
|
+
end
|
7827
|
+
|
7828
|
+
# def call_operator: () -> String?
|
7829
|
+
def call_operator
|
7830
|
+
call_operator_loc&.slice
|
7831
|
+
end
|
7832
|
+
|
7833
|
+
# def opening: () -> String
|
7834
|
+
def opening
|
7835
|
+
opening_loc.slice
|
7836
|
+
end
|
7837
|
+
|
7838
|
+
# def closing: () -> String
|
7839
|
+
def closing
|
7840
|
+
closing_loc.slice
|
7841
|
+
end
|
7842
|
+
|
7843
|
+
# def safe_navigation?: () -> bool
|
7844
|
+
def safe_navigation?
|
7845
|
+
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
|
7846
|
+
end
|
7847
|
+
|
7848
|
+
# def variable_call?: () -> bool
|
7849
|
+
def variable_call?
|
7850
|
+
flags.anybits?(CallNodeFlags::VARIABLE_CALL)
|
7851
|
+
end
|
7852
|
+
|
7853
|
+
# def operator: () -> String
|
7854
|
+
def operator
|
7855
|
+
operator_loc.slice
|
7856
|
+
end
|
7857
|
+
|
7858
|
+
def inspect(inspector = NodeInspector.new)
|
7859
|
+
inspector << inspector.header(self)
|
7860
|
+
if (receiver = self.receiver).nil?
|
7861
|
+
inspector << "├── receiver: ∅\n"
|
7862
|
+
else
|
7863
|
+
inspector << "├── receiver:\n"
|
7864
|
+
inspector << receiver.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
|
7865
|
+
end
|
7866
|
+
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
|
7867
|
+
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
|
7868
|
+
if (arguments = self.arguments).nil?
|
7869
|
+
inspector << "├── arguments: ∅\n"
|
7870
|
+
else
|
7871
|
+
inspector << "├── arguments:\n"
|
7872
|
+
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
|
7873
|
+
end
|
7874
|
+
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
|
7875
|
+
if (block = self.block).nil?
|
7876
|
+
inspector << "├── block: ∅\n"
|
7877
|
+
else
|
7878
|
+
inspector << "├── block:\n"
|
7879
|
+
inspector << block.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
|
7880
|
+
end
|
7881
|
+
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?)].compact
|
7882
|
+
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
|
7883
|
+
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
|
7884
|
+
inspector << "└── value:\n"
|
7885
|
+
inspector << inspector.child_node(value, " ")
|
7886
|
+
inspector.to_str
|
7887
|
+
end
|
7888
|
+
|
7889
|
+
# Sometimes you want to check an instance of a node against a list of
|
7890
|
+
# classes to see what kind of behavior to perform. Usually this is done by
|
7891
|
+
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
|
7892
|
+
# case statement and doing `case node; when cls1; when cls2; end`. Both of
|
7893
|
+
# these approaches are relatively slow because of the constant lookups,
|
7894
|
+
# method calls, and/or array allocations.
|
7895
|
+
#
|
7896
|
+
# Instead, you can call #type, which will return to you a symbol that you
|
7897
|
+
# can use for comparison. This is faster than the other approaches because
|
7898
|
+
# it uses a single integer comparison, but also because if you're on CRuby
|
7899
|
+
# you can take advantage of the fact that case statements with all symbol
|
7900
|
+
# keys will use a jump table.
|
7901
|
+
#
|
7902
|
+
# def type: () -> Symbol
|
7903
|
+
def type
|
7904
|
+
:index_and_write_node
|
7905
|
+
end
|
7906
|
+
|
7907
|
+
# Similar to #type, this method returns a symbol that you can use for
|
7908
|
+
# splitting on the type of the node without having to do a long === chain.
|
7909
|
+
# Note that like #type, it will still be slower than using == for a single
|
7910
|
+
# class, but should be faster in a case statement or an array comparison.
|
7911
|
+
#
|
7912
|
+
# def self.type: () -> Symbol
|
7913
|
+
def self.type
|
7914
|
+
:index_and_write_node
|
7915
|
+
end
|
7916
|
+
end
|
7917
|
+
|
7918
|
+
# Represents the use of an assignment operator on a call to `[]`.
|
7919
|
+
#
|
7920
|
+
# foo.bar[baz] += value
|
7921
|
+
# ^^^^^^^^^^^^^^^^^^^^^
|
7922
|
+
class IndexOperatorWriteNode < Node
|
7923
|
+
# attr_reader receiver: Node?
|
7924
|
+
attr_reader :receiver
|
7925
|
+
|
7926
|
+
# attr_reader call_operator_loc: Location?
|
7927
|
+
attr_reader :call_operator_loc
|
7928
|
+
|
7929
|
+
# attr_reader opening_loc: Location
|
7930
|
+
attr_reader :opening_loc
|
7931
|
+
|
7932
|
+
# attr_reader arguments: ArgumentsNode?
|
7933
|
+
attr_reader :arguments
|
7934
|
+
|
7935
|
+
# attr_reader closing_loc: Location
|
7936
|
+
attr_reader :closing_loc
|
7937
|
+
|
7938
|
+
# attr_reader block: Node?
|
7939
|
+
attr_reader :block
|
7940
|
+
|
7941
|
+
# attr_reader flags: Integer
|
7942
|
+
private attr_reader :flags
|
7943
|
+
|
7944
|
+
# attr_reader operator: Symbol
|
7945
|
+
attr_reader :operator
|
7946
|
+
|
7947
|
+
# attr_reader operator_loc: Location
|
7948
|
+
attr_reader :operator_loc
|
7949
|
+
|
7950
|
+
# attr_reader value: Node
|
7951
|
+
attr_reader :value
|
7952
|
+
|
7953
|
+
# def initialize: (receiver: Node?, call_operator_loc: Location?, opening_loc: Location, arguments: ArgumentsNode?, closing_loc: Location, block: Node?, flags: Integer, operator: Symbol, operator_loc: Location, value: Node, location: Location) -> void
|
7954
|
+
def initialize(receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, flags, operator, operator_loc, value, location)
|
7955
|
+
@receiver = receiver
|
7956
|
+
@call_operator_loc = call_operator_loc
|
7957
|
+
@opening_loc = opening_loc
|
7958
|
+
@arguments = arguments
|
7959
|
+
@closing_loc = closing_loc
|
7960
|
+
@block = block
|
7961
|
+
@flags = flags
|
7962
|
+
@operator = operator
|
7963
|
+
@operator_loc = operator_loc
|
7964
|
+
@value = value
|
7965
|
+
@location = location
|
7966
|
+
end
|
7967
|
+
|
7968
|
+
# def accept: (visitor: Visitor) -> void
|
7969
|
+
def accept(visitor)
|
7970
|
+
visitor.visit_index_operator_write_node(self)
|
7971
|
+
end
|
7972
|
+
|
7973
|
+
# def child_nodes: () -> Array[nil | Node]
|
7974
|
+
def child_nodes
|
7975
|
+
[receiver, arguments, block, value]
|
7976
|
+
end
|
7977
|
+
|
7978
|
+
# def compact_child_nodes: () -> Array[Node]
|
7979
|
+
def compact_child_nodes
|
7980
|
+
compact = []
|
7981
|
+
compact << receiver if receiver
|
7982
|
+
compact << arguments if arguments
|
7983
|
+
compact << block if block
|
7984
|
+
compact << value
|
7985
|
+
compact
|
7986
|
+
end
|
7987
|
+
|
7988
|
+
# def comment_targets: () -> Array[Node | Location]
|
7989
|
+
def comment_targets
|
7990
|
+
[*receiver, *call_operator_loc, opening_loc, *arguments, closing_loc, *block, operator_loc, value]
|
7991
|
+
end
|
7992
|
+
|
7993
|
+
# def copy: (**params) -> IndexOperatorWriteNode
|
7994
|
+
def copy(**params)
|
7995
|
+
IndexOperatorWriteNode.new(
|
7996
|
+
params.fetch(:receiver) { receiver },
|
7997
|
+
params.fetch(:call_operator_loc) { call_operator_loc },
|
7998
|
+
params.fetch(:opening_loc) { opening_loc },
|
7999
|
+
params.fetch(:arguments) { arguments },
|
8000
|
+
params.fetch(:closing_loc) { closing_loc },
|
8001
|
+
params.fetch(:block) { block },
|
8002
|
+
params.fetch(:flags) { flags },
|
8003
|
+
params.fetch(:operator) { operator },
|
8004
|
+
params.fetch(:operator_loc) { operator_loc },
|
8005
|
+
params.fetch(:value) { value },
|
8006
|
+
params.fetch(:location) { location },
|
8007
|
+
)
|
8008
|
+
end
|
8009
|
+
|
8010
|
+
# def deconstruct: () -> Array[nil | Node]
|
8011
|
+
alias deconstruct child_nodes
|
8012
|
+
|
8013
|
+
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
|
8014
|
+
def deconstruct_keys(keys)
|
8015
|
+
{ receiver: receiver, call_operator_loc: call_operator_loc, opening_loc: opening_loc, arguments: arguments, closing_loc: closing_loc, block: block, flags: flags, operator: operator, operator_loc: operator_loc, value: value, location: location }
|
8016
|
+
end
|
8017
|
+
|
8018
|
+
# def call_operator: () -> String?
|
8019
|
+
def call_operator
|
8020
|
+
call_operator_loc&.slice
|
8021
|
+
end
|
8022
|
+
|
8023
|
+
# def opening: () -> String
|
8024
|
+
def opening
|
8025
|
+
opening_loc.slice
|
8026
|
+
end
|
8027
|
+
|
8028
|
+
# def closing: () -> String
|
8029
|
+
def closing
|
8030
|
+
closing_loc.slice
|
8031
|
+
end
|
8032
|
+
|
8033
|
+
# def safe_navigation?: () -> bool
|
8034
|
+
def safe_navigation?
|
8035
|
+
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
|
8036
|
+
end
|
8037
|
+
|
8038
|
+
# def variable_call?: () -> bool
|
8039
|
+
def variable_call?
|
8040
|
+
flags.anybits?(CallNodeFlags::VARIABLE_CALL)
|
8041
|
+
end
|
8042
|
+
|
8043
|
+
def inspect(inspector = NodeInspector.new)
|
8044
|
+
inspector << inspector.header(self)
|
8045
|
+
if (receiver = self.receiver).nil?
|
8046
|
+
inspector << "├── receiver: ∅\n"
|
8047
|
+
else
|
8048
|
+
inspector << "├── receiver:\n"
|
8049
|
+
inspector << receiver.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
|
8050
|
+
end
|
8051
|
+
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
|
8052
|
+
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
|
8053
|
+
if (arguments = self.arguments).nil?
|
8054
|
+
inspector << "├── arguments: ∅\n"
|
8055
|
+
else
|
8056
|
+
inspector << "├── arguments:\n"
|
8057
|
+
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
|
8058
|
+
end
|
8059
|
+
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
|
8060
|
+
if (block = self.block).nil?
|
8061
|
+
inspector << "├── block: ∅\n"
|
8062
|
+
else
|
8063
|
+
inspector << "├── block:\n"
|
8064
|
+
inspector << block.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
|
8065
|
+
end
|
8066
|
+
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?)].compact
|
8067
|
+
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
|
8068
|
+
inspector << "├── operator: #{operator.inspect}\n"
|
8069
|
+
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
|
8070
|
+
inspector << "└── value:\n"
|
8071
|
+
inspector << inspector.child_node(value, " ")
|
8072
|
+
inspector.to_str
|
8073
|
+
end
|
8074
|
+
|
8075
|
+
# Sometimes you want to check an instance of a node against a list of
|
8076
|
+
# classes to see what kind of behavior to perform. Usually this is done by
|
8077
|
+
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
|
8078
|
+
# case statement and doing `case node; when cls1; when cls2; end`. Both of
|
8079
|
+
# these approaches are relatively slow because of the constant lookups,
|
8080
|
+
# method calls, and/or array allocations.
|
8081
|
+
#
|
8082
|
+
# Instead, you can call #type, which will return to you a symbol that you
|
8083
|
+
# can use for comparison. This is faster than the other approaches because
|
8084
|
+
# it uses a single integer comparison, but also because if you're on CRuby
|
8085
|
+
# you can take advantage of the fact that case statements with all symbol
|
8086
|
+
# keys will use a jump table.
|
8087
|
+
#
|
8088
|
+
# def type: () -> Symbol
|
8089
|
+
def type
|
8090
|
+
:index_operator_write_node
|
8091
|
+
end
|
8092
|
+
|
8093
|
+
# Similar to #type, this method returns a symbol that you can use for
|
8094
|
+
# splitting on the type of the node without having to do a long === chain.
|
8095
|
+
# Note that like #type, it will still be slower than using == for a single
|
8096
|
+
# class, but should be faster in a case statement or an array comparison.
|
8097
|
+
#
|
8098
|
+
# def self.type: () -> Symbol
|
8099
|
+
def self.type
|
8100
|
+
:index_operator_write_node
|
8101
|
+
end
|
8102
|
+
end
|
8103
|
+
|
8104
|
+
# Represents the use of the `||=` operator on a call to `[]`.
|
8105
|
+
#
|
8106
|
+
# foo.bar[baz] ||= value
|
8107
|
+
# ^^^^^^^^^^^^^^^^^^^^^^
|
8108
|
+
class IndexOrWriteNode < Node
|
8109
|
+
# attr_reader receiver: Node?
|
8110
|
+
attr_reader :receiver
|
8111
|
+
|
8112
|
+
# attr_reader call_operator_loc: Location?
|
8113
|
+
attr_reader :call_operator_loc
|
8114
|
+
|
8115
|
+
# attr_reader opening_loc: Location
|
8116
|
+
attr_reader :opening_loc
|
8117
|
+
|
8118
|
+
# attr_reader arguments: ArgumentsNode?
|
8119
|
+
attr_reader :arguments
|
8120
|
+
|
8121
|
+
# attr_reader closing_loc: Location
|
8122
|
+
attr_reader :closing_loc
|
8123
|
+
|
8124
|
+
# attr_reader block: Node?
|
8125
|
+
attr_reader :block
|
8126
|
+
|
8127
|
+
# attr_reader flags: Integer
|
8128
|
+
private attr_reader :flags
|
8129
|
+
|
8130
|
+
# attr_reader operator_loc: Location
|
8131
|
+
attr_reader :operator_loc
|
8132
|
+
|
8133
|
+
# attr_reader value: Node
|
8134
|
+
attr_reader :value
|
8135
|
+
|
8136
|
+
# def initialize: (receiver: Node?, call_operator_loc: Location?, opening_loc: Location, arguments: ArgumentsNode?, closing_loc: Location, block: Node?, flags: Integer, operator_loc: Location, value: Node, location: Location) -> void
|
8137
|
+
def initialize(receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, flags, operator_loc, value, location)
|
8138
|
+
@receiver = receiver
|
8139
|
+
@call_operator_loc = call_operator_loc
|
8140
|
+
@opening_loc = opening_loc
|
8141
|
+
@arguments = arguments
|
8142
|
+
@closing_loc = closing_loc
|
8143
|
+
@block = block
|
8144
|
+
@flags = flags
|
8145
|
+
@operator_loc = operator_loc
|
8146
|
+
@value = value
|
8147
|
+
@location = location
|
8148
|
+
end
|
8149
|
+
|
8150
|
+
# def accept: (visitor: Visitor) -> void
|
8151
|
+
def accept(visitor)
|
8152
|
+
visitor.visit_index_or_write_node(self)
|
8153
|
+
end
|
8154
|
+
|
8155
|
+
# def child_nodes: () -> Array[nil | Node]
|
8156
|
+
def child_nodes
|
8157
|
+
[receiver, arguments, block, value]
|
8158
|
+
end
|
8159
|
+
|
8160
|
+
# def compact_child_nodes: () -> Array[Node]
|
8161
|
+
def compact_child_nodes
|
8162
|
+
compact = []
|
8163
|
+
compact << receiver if receiver
|
8164
|
+
compact << arguments if arguments
|
8165
|
+
compact << block if block
|
8166
|
+
compact << value
|
8167
|
+
compact
|
8168
|
+
end
|
8169
|
+
|
8170
|
+
# def comment_targets: () -> Array[Node | Location]
|
8171
|
+
def comment_targets
|
8172
|
+
[*receiver, *call_operator_loc, opening_loc, *arguments, closing_loc, *block, operator_loc, value]
|
8173
|
+
end
|
8174
|
+
|
8175
|
+
# def copy: (**params) -> IndexOrWriteNode
|
8176
|
+
def copy(**params)
|
8177
|
+
IndexOrWriteNode.new(
|
8178
|
+
params.fetch(:receiver) { receiver },
|
8179
|
+
params.fetch(:call_operator_loc) { call_operator_loc },
|
8180
|
+
params.fetch(:opening_loc) { opening_loc },
|
8181
|
+
params.fetch(:arguments) { arguments },
|
8182
|
+
params.fetch(:closing_loc) { closing_loc },
|
8183
|
+
params.fetch(:block) { block },
|
8184
|
+
params.fetch(:flags) { flags },
|
8185
|
+
params.fetch(:operator_loc) { operator_loc },
|
8186
|
+
params.fetch(:value) { value },
|
8187
|
+
params.fetch(:location) { location },
|
8188
|
+
)
|
8189
|
+
end
|
8190
|
+
|
8191
|
+
# def deconstruct: () -> Array[nil | Node]
|
8192
|
+
alias deconstruct child_nodes
|
8193
|
+
|
8194
|
+
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
|
8195
|
+
def deconstruct_keys(keys)
|
8196
|
+
{ receiver: receiver, call_operator_loc: call_operator_loc, opening_loc: opening_loc, arguments: arguments, closing_loc: closing_loc, block: block, flags: flags, operator_loc: operator_loc, value: value, location: location }
|
8197
|
+
end
|
8198
|
+
|
8199
|
+
# def call_operator: () -> String?
|
8200
|
+
def call_operator
|
8201
|
+
call_operator_loc&.slice
|
8202
|
+
end
|
8203
|
+
|
8204
|
+
# def opening: () -> String
|
8205
|
+
def opening
|
8206
|
+
opening_loc.slice
|
8207
|
+
end
|
8208
|
+
|
8209
|
+
# def closing: () -> String
|
8210
|
+
def closing
|
8211
|
+
closing_loc.slice
|
8212
|
+
end
|
8213
|
+
|
8214
|
+
# def safe_navigation?: () -> bool
|
8215
|
+
def safe_navigation?
|
8216
|
+
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
|
8217
|
+
end
|
8218
|
+
|
8219
|
+
# def variable_call?: () -> bool
|
8220
|
+
def variable_call?
|
8221
|
+
flags.anybits?(CallNodeFlags::VARIABLE_CALL)
|
8222
|
+
end
|
8223
|
+
|
8224
|
+
# def operator: () -> String
|
8225
|
+
def operator
|
8226
|
+
operator_loc.slice
|
8227
|
+
end
|
8228
|
+
|
8229
|
+
def inspect(inspector = NodeInspector.new)
|
8230
|
+
inspector << inspector.header(self)
|
8231
|
+
if (receiver = self.receiver).nil?
|
8232
|
+
inspector << "├── receiver: ∅\n"
|
8233
|
+
else
|
8234
|
+
inspector << "├── receiver:\n"
|
8235
|
+
inspector << receiver.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
|
8236
|
+
end
|
8237
|
+
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
|
8238
|
+
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
|
8239
|
+
if (arguments = self.arguments).nil?
|
8240
|
+
inspector << "├── arguments: ∅\n"
|
8241
|
+
else
|
8242
|
+
inspector << "├── arguments:\n"
|
8243
|
+
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
|
8244
|
+
end
|
8245
|
+
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
|
8246
|
+
if (block = self.block).nil?
|
8247
|
+
inspector << "├── block: ∅\n"
|
8248
|
+
else
|
8249
|
+
inspector << "├── block:\n"
|
8250
|
+
inspector << block.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
|
8251
|
+
end
|
8252
|
+
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?)].compact
|
8253
|
+
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
|
8254
|
+
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
|
8255
|
+
inspector << "└── value:\n"
|
8256
|
+
inspector << inspector.child_node(value, " ")
|
8257
|
+
inspector.to_str
|
8258
|
+
end
|
8259
|
+
|
8260
|
+
# Sometimes you want to check an instance of a node against a list of
|
8261
|
+
# classes to see what kind of behavior to perform. Usually this is done by
|
8262
|
+
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
|
8263
|
+
# case statement and doing `case node; when cls1; when cls2; end`. Both of
|
8264
|
+
# these approaches are relatively slow because of the constant lookups,
|
8265
|
+
# method calls, and/or array allocations.
|
8266
|
+
#
|
8267
|
+
# Instead, you can call #type, which will return to you a symbol that you
|
8268
|
+
# can use for comparison. This is faster than the other approaches because
|
8269
|
+
# it uses a single integer comparison, but also because if you're on CRuby
|
8270
|
+
# you can take advantage of the fact that case statements with all symbol
|
8271
|
+
# keys will use a jump table.
|
8272
|
+
#
|
8273
|
+
# def type: () -> Symbol
|
8274
|
+
def type
|
8275
|
+
:index_or_write_node
|
8276
|
+
end
|
8277
|
+
|
8278
|
+
# Similar to #type, this method returns a symbol that you can use for
|
8279
|
+
# splitting on the type of the node without having to do a long === chain.
|
8280
|
+
# Note that like #type, it will still be slower than using == for a single
|
8281
|
+
# class, but should be faster in a case statement or an array comparison.
|
8282
|
+
#
|
8283
|
+
# def self.type: () -> Symbol
|
8284
|
+
def self.type
|
8285
|
+
:index_or_write_node
|
8286
|
+
end
|
8287
|
+
end
|
8288
|
+
|
7829
8289
|
# Represents the use of the `&&=` operator for assignment to an instance variable.
|
7830
8290
|
#
|
7831
8291
|
# @target &&= value
|