ruby-next-core 0.10.0 → 0.10.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyNext
4
+ module Language
5
+ module Rewriters
6
+ class RightHandAssignment < Base
7
+ NAME = "right-hand-assignment"
8
+ SYNTAX_PROBE = "1 + 2 => a"
9
+ MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
10
+
11
+ def on_rasgn(node)
12
+ context.track! self
13
+
14
+ node = super(node)
15
+
16
+ val_node, asgn_node = *node
17
+
18
+ remove(val_node.loc.expression.end.join(asgn_node.loc.expression))
19
+ insert_before(val_node.loc.expression, "#{asgn_node.loc.expression.source} = ")
20
+
21
+ asgn_node.updated(
22
+ nil,
23
+ asgn_node.children + [val_node]
24
+ )
25
+ end
26
+
27
+ def on_vasgn(node)
28
+ return super(node) unless rightward?(node)
29
+
30
+ context.track! self
31
+
32
+ name, val_node = *node
33
+
34
+ remove(val_node.loc.expression.end.join(node.loc.name))
35
+ insert_before(val_node.loc.expression, "#{name} = ")
36
+
37
+ super(node)
38
+ end
39
+
40
+ def on_casgn(node)
41
+ return super(node) unless rightward?(node)
42
+
43
+ context.track! self
44
+
45
+ scope_node, name, val_node = *node
46
+
47
+ if scope_node
48
+ scope = scope_node.type == :cbase ? scope_node.loc.expression.source : "#{scope_node.loc.expression.source}::"
49
+ name = "#{scope}#{name}"
50
+ end
51
+
52
+ remove(val_node.loc.expression.end.join(node.loc.name))
53
+ insert_before(val_node.loc.expression, "#{name} = ")
54
+
55
+ super(node)
56
+ end
57
+
58
+ def on_mrasgn(node)
59
+ context.track! self
60
+
61
+ node = super(node)
62
+
63
+ lhs, rhs = *node
64
+
65
+ replace(lhs.loc.expression.end.join(rhs.loc.expression), ")")
66
+ insert_before(lhs.loc.expression, "#{rhs.loc.expression.source} = (")
67
+
68
+ node.updated(
69
+ :masgn,
70
+ [rhs, lhs]
71
+ )
72
+ end
73
+
74
+ def on_masgn(node)
75
+ return super(node) unless rightward?(node)
76
+
77
+ context.track! self
78
+
79
+ rhs, lhs = *node
80
+
81
+ replace(lhs.loc.expression.end.join(rhs.loc.expression), ")")
82
+ insert_before(lhs.loc.expression, "#{rhs.loc.expression.source} = (")
83
+
84
+ node = super(node)
85
+
86
+ lhs, rhs = *node
87
+
88
+ node.updated(
89
+ nil,
90
+ [
91
+ lhs,
92
+ s(:begin, rhs)
93
+ ]
94
+ )
95
+ end
96
+
97
+ private
98
+
99
+ def rightward?(node)
100
+ # Location could be empty for node built by rewriters
101
+ return false unless ((!node.loc.nil? || nil) && node.loc.operator)
102
+
103
+ assignee_loc =
104
+ if node.type == :masgn
105
+ node.children[0].loc.expression
106
+ else
107
+ node.loc.name
108
+ end
109
+
110
+ return false unless assignee_loc
111
+
112
+ assignee_loc.begin_pos > node.loc.operator.end_pos
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -6,7 +6,7 @@ module RubyNext
6
6
 
7
7
  if $LOAD_PATH.respond_to?(:resolve_feature_path)
8
8
  def resolve_feature_path(feature)
9
- ((!$LOAD_PATH.resolve_feature_path(feature).nil?) || nil) && $LOAD_PATH.resolve_feature_path(feature).last
9
+ ((!$LOAD_PATH.resolve_feature_path(feature).nil? || nil) && $LOAD_PATH.resolve_feature_path(feature).last)
10
10
  rescue LoadError
11
11
  end
12
12
  else
@@ -148,6 +148,9 @@ module RubyNext
148
148
 
149
149
  # Then, generate the source code for the next version
150
150
  transpile path, contents, version: version
151
+ rescue SyntaxError, StandardError => e
152
+ warn "Failed to transpile #{path}: #{e.class} — #{e.message}"
153
+ exit 1
151
154
  end
152
155
 
153
156
  def save(contents, path, version)
@@ -6,7 +6,7 @@ module RubyNext
6
6
  class ArgsForward < Base
7
7
  NAME = "args-forward"
8
8
  SYNTAX_PROBE = "obj = Object.new; def obj.foo(...) super(1, ...); end"
9
- MIN_SUPPORTED_VERSION = Gem::Version.new("2.7.2")
9
+ MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
10
10
 
11
11
  REST = :__rest__
12
12
  BLOCK = :__block__
@@ -112,7 +112,8 @@ module RubyNext
112
112
 
113
113
  def unparse(ast)
114
114
  return ast if ast.is_a?(String)
115
- Unparser.unparse(ast)
115
+
116
+ Unparser.unparse(ast).chomp
116
117
  end
117
118
 
118
119
  attr_reader :context
@@ -16,9 +16,9 @@ module RubyNext
16
16
  proc_or_lambda, num, body = *node.children
17
17
 
18
18
  if proc_or_lambda.type == :lambda
19
- insert_before(node.loc.begin, "(#{unparse(proc_args(num))})")
19
+ insert_before(node.loc.begin, "(#{proc_args_str(num)})")
20
20
  else
21
- insert_after(node.loc.begin, " |#{unparse(proc_args(num))}|")
21
+ insert_after(node.loc.begin, " |#{proc_args_str(num)}|")
22
22
  end
23
23
 
24
24
  node.updated(
@@ -33,6 +33,10 @@ module RubyNext
33
33
 
34
34
  private
35
35
 
36
+ def proc_args_str(n)
37
+ (1..n).map { |numero| "_#{numero}" }.join(", ")
38
+ end
39
+
36
40
  def proc_args(n)
37
41
  return s(:args, s(:procarg0, s(:arg, :_1))) if n == 1
38
42
 
@@ -244,7 +244,7 @@ module RubyNext
244
244
  @predicates = Predicates::CaseIn.new
245
245
 
246
246
  matchee_ast =
247
- s(:lvasgn, MATCHEE, node.children[0])
247
+ s(:begin, s(:lvasgn, MATCHEE, node.children[0]))
248
248
 
249
249
  patterns = locals.with(
250
250
  matchee: MATCHEE,
@@ -273,7 +273,7 @@ module RubyNext
273
273
  @predicates = Predicates::Noop.new
274
274
 
275
275
  matchee =
276
- s(:lvasgn, MATCHEE, node.children[0])
276
+ s(:begin, s(:lvasgn, MATCHEE, node.children[0]))
277
277
 
278
278
  pattern =
279
279
  locals.with(
@@ -285,9 +285,10 @@ module RubyNext
285
285
  :"#{node.children[1].type}_clause",
286
286
  node.children[1]
287
287
  ).then do |node|
288
- s(:or,
289
- node,
290
- no_matching_pattern)
288
+ s(:begin,
289
+ s(:or,
290
+ node,
291
+ no_matching_pattern))
291
292
  end
292
293
  end
293
294
 
@@ -378,9 +379,10 @@ module RubyNext
378
379
  predicates.const(case_eq_clause(const, right), const).then do |node|
379
380
  next node if pattern.nil?
380
381
 
381
- s(:and,
382
- node,
383
- send(:"#{pattern.type}_clause", pattern))
382
+ s(:begin,
383
+ s(:and,
384
+ node,
385
+ send(:"#{pattern.type}_clause", pattern)))
384
386
  end
385
387
  end
386
388
 
@@ -391,13 +393,14 @@ module RubyNext
391
393
  send :"#{child.type}_clause", child
392
394
  end
393
395
  end
394
- s(:or, *children)
396
+ s(:begin, s(:or, *children))
395
397
  end
396
398
 
397
399
  def match_as_clause(node, right = s(:lvar, locals[:matchee]))
398
- s(:and,
399
- send(:"#{node.children[0].type}_clause", node.children[0], right),
400
- match_var_clause(node.children[1], right))
400
+ s(:begin,
401
+ s(:and,
402
+ send(:"#{node.children[0].type}_clause", node.children[0], right),
403
+ match_var_clause(node.children[1], right)))
401
404
  end
402
405
 
403
406
  def match_var_clause(node, left = s(:lvar, locals[:matchee]))
@@ -405,9 +408,10 @@ module RubyNext
405
408
 
406
409
  check_match_var_alternation! node.children[0]
407
410
 
408
- s(:or,
409
- s(:lvasgn, node.children[0], left),
410
- s(:true))
411
+ s(:begin,
412
+ s(:or,
413
+ s(:begin, s(:lvasgn, node.children[0], left)),
414
+ s(:true)))
411
415
  end
412
416
 
413
417
  def pin_clause(node, right = s(:lvar, locals[:matchee]))
@@ -417,8 +421,8 @@ module RubyNext
417
421
 
418
422
  def case_eq_clause(node, right = s(:lvar, locals[:matchee]))
419
423
  predicates.terminate!
420
- s(:send,
421
- process(node), :===, right)
424
+ s(:begin, s(:send,
425
+ process(node), :===, right))
422
426
  end
423
427
 
424
428
  #=========== ARRAY PATTERN (START) ===============
@@ -429,10 +433,11 @@ module RubyNext
429
433
  # if there is no rest or tail, match the size first
430
434
  unless node.type == :array_pattern_with_tail || node.children.any? { |n| n.type == :match_rest }
431
435
  size_check = predicates.array_size(
432
- s(:send,
433
- node.children.size.to_ast_node,
434
- :==,
435
- s(:send, s(:lvar, locals[:arr]), :size)),
436
+ s(:begin,
437
+ s(:send,
438
+ node.children.size.to_ast_node,
439
+ :==,
440
+ s(:send, s(:lvar, locals[:arr]), :size))),
436
441
  node.children.size
437
442
  )
438
443
  end
@@ -448,9 +453,10 @@ module RubyNext
448
453
 
449
454
  right = s(:and, size_check, right) if size_check
450
455
 
451
- s(:and,
452
- dnode,
453
- right)
456
+ s(:begin,
457
+ s(:and,
458
+ dnode,
459
+ right))
454
460
  end
455
461
  end
456
462
 
@@ -468,14 +474,17 @@ module RubyNext
468
474
  predicates.array_deconstructed(
469
475
  s(:and,
470
476
  respond_check,
471
- s(:and,
472
- s(:or,
473
- s(:lvasgn, locals[:arr], right),
474
- s(:true)),
475
- s(:or,
476
- s(:send,
477
- s(:const, nil, :Array), :===, s(:lvar, locals[:arr])),
478
- raise_error(:TypeError, "#deconstruct must return Array"))))
477
+ s(:begin,
478
+ s(:and,
479
+ s(:begin,
480
+ s(:or,
481
+ s(:begin, s(:lvasgn, locals[:arr], right)),
482
+ s(:true))),
483
+ s(:begin,
484
+ s(:or,
485
+ s(:send,
486
+ s(:const, nil, :Array), :===, s(:lvar, locals[:arr])),
487
+ raise_error(:TypeError, "#deconstruct must return Array"))))))
479
488
  )
480
489
  end
481
490
 
@@ -485,9 +494,10 @@ module RubyNext
485
494
  send("#{head.type}_array_element", head, index).then do |node|
486
495
  next node if tail.empty?
487
496
 
488
- s(:and,
489
- node,
490
- array_element(index + 1, *tail))
497
+ s(:begin,
498
+ s(:and,
499
+ node,
500
+ array_element(index + 1, *tail)))
491
501
  end
492
502
  end
493
503
 
@@ -526,15 +536,17 @@ module RubyNext
526
536
 
527
537
  pattern = array_rest_element(*nodes, index).then do |needle|
528
538
  next needle unless head_match
529
- s(:and,
530
- needle,
531
- head_match)
539
+ s(:begin,
540
+ s(:and,
541
+ needle,
542
+ head_match))
532
543
  end.then do |headed_needle|
533
544
  next headed_needle unless tail_match
534
545
 
535
- s(:and,
536
- headed_needle,
537
- tail_match)
546
+ s(:begin,
547
+ s(:and,
548
+ headed_needle,
549
+ tail_match))
538
550
  end
539
551
 
540
552
  s(:block,
@@ -550,13 +562,14 @@ module RubyNext
550
562
  next block if match_vars.empty?
551
563
 
552
564
  # We need to declare match vars outside of `find` block
553
- locals_declare = s(:masgn,
565
+ locals_declare = s(:begin, s(:masgn,
554
566
  s(:mlhs, *match_vars),
555
- s(:nil))
567
+ s(:nil)))
556
568
 
557
- s(:or,
558
- locals_declare,
559
- block)
569
+ s(:begin,
570
+ s(:or,
571
+ locals_declare,
572
+ block))
560
573
  end
561
574
  end
562
575
 
@@ -575,18 +588,20 @@ module RubyNext
575
588
 
576
589
  return rest if tail.empty?
577
590
 
578
- s(:and,
579
- rest,
580
- array_rest_element(*tail, -(size - 1)))
591
+ s(:begin,
592
+ s(:and,
593
+ rest,
594
+ array_rest_element(*tail, -(size - 1))))
581
595
  end
582
596
 
583
597
  def array_rest_element(head, *tail, index)
584
598
  send("#{head.type}_array_element", head, index).then do |node|
585
599
  next node if tail.empty?
586
600
 
587
- s(:and,
588
- node,
589
- array_rest_element(*tail, index + 1))
601
+ s(:begin,
602
+ s(:and,
603
+ node,
604
+ array_rest_element(*tail, index + 1)))
590
605
  end
591
606
  end
592
607
 
@@ -610,7 +625,7 @@ module RubyNext
610
625
  children = node.children.map do |child, i|
611
626
  send :"#{child.type}_array_element", child, index
612
627
  end
613
- s(:or, *children)
628
+ s(:begin, s(:or, *children))
614
629
  end
615
630
 
616
631
  def match_var_array_element(node, index)
@@ -661,18 +676,20 @@ module RubyNext
661
676
  elsif specified_key_names.empty?
662
677
  hash_element(*node.children)
663
678
  else
664
- s(:and,
665
- having_hash_keys(specified_key_names),
666
- hash_element(*node.children))
679
+ s(:begin,
680
+ s(:and,
681
+ having_hash_keys(specified_key_names),
682
+ hash_element(*node.children)))
667
683
  end
668
684
 
669
685
  predicates.pop
670
686
 
671
687
  next dnode if right.nil?
672
688
 
673
- s(:and,
674
- dnode,
675
- right)
689
+ s(:begin,
690
+ s(:and,
691
+ dnode,
692
+ right))
676
693
  end
677
694
  end
678
695
 
@@ -715,7 +732,7 @@ module RubyNext
715
732
  # Duplicate the source hash when matching **rest, 'cause we mutate it
716
733
  hash_dup =
717
734
  if @hash_match_rest
718
- s(:lvasgn, locals[:hash], s(:send, s(:lvar, locals[:hash, :src]), :dup))
735
+ s(:begin, s(:lvasgn, locals[:hash], s(:send, s(:lvar, locals[:hash, :src]), :dup)))
719
736
  else
720
737
  s(:true)
721
738
  end
@@ -728,29 +745,33 @@ module RubyNext
728
745
  key_names = keys.children.map { |node| node.children.last }
729
746
  predicates.push locals[:hash]
730
747
 
731
- s(:lvasgn, deconstruct_name,
748
+ s(:begin, s(:lvasgn, deconstruct_name,
732
749
  s(:send,
733
- matchee, :deconstruct_keys, keys)).then do |dnode|
750
+ matchee, :deconstruct_keys, keys))).then do |dnode|
734
751
  next dnode if respond_to_checked
735
752
 
736
753
  s(:and,
737
754
  respond_check,
738
- s(:and,
739
- s(:or,
740
- dnode,
741
- s(:true)),
742
- s(:or,
743
- s(:send,
744
- s(:const, nil, :Hash), :===, s(:lvar, deconstruct_name)),
745
- raise_error(:TypeError, "#deconstruct_keys must return Hash"))))
755
+ s(:begin,
756
+ s(:and,
757
+ s(:begin,
758
+ s(:or,
759
+ dnode,
760
+ s(:true))),
761
+ s(:begin,
762
+ s(:or,
763
+ s(:send,
764
+ s(:const, nil, :Hash), :===, s(:lvar, deconstruct_name)),
765
+ raise_error(:TypeError, "#deconstruct_keys must return Hash"))))))
746
766
  end.then do |dnode|
747
767
  predicates.hash_deconstructed(dnode, key_names)
748
768
  end.then do |dnode|
749
769
  next dnode unless @hash_match_rest
750
770
 
751
- s(:and,
752
- dnode,
753
- hash_dup)
771
+ s(:begin,
772
+ s(:and,
773
+ dnode,
774
+ hash_dup))
754
775
  end
755
776
  end
756
777
 
@@ -780,9 +801,10 @@ module RubyNext
780
801
 
781
802
  next node if right.nil?
782
803
 
783
- s(:and,
784
- node,
785
- right)
804
+ s(:begin,
805
+ s(:and,
806
+ node,
807
+ right))
786
808
  end
787
809
  end
788
810
 
@@ -792,7 +814,7 @@ module RubyNext
792
814
  end
793
815
 
794
816
  def match_alt_hash_element(node, key)
795
- element_node = s(:lvasgn, locals[:hash, :el], hash_value_at(key))
817
+ element_node = s(:begin, s(:lvasgn, locals[:hash, :el], hash_value_at(key)))
796
818
 
797
819
  children = locals.with(hash_element: locals[:hash, :el]) do
798
820
  node.children.map do |child, i|
@@ -800,11 +822,14 @@ module RubyNext
800
822
  end
801
823
  end
802
824
 
803
- s(:and,
804
- s(:or,
805
- element_node,
806
- s(:true)),
807
- s(:or, *children))
825
+ s(:begin,
826
+ s(:and,
827
+ s(:begin,
828
+ s(:or,
829
+ element_node,
830
+ s(:true))),
831
+ s(:begin,
832
+ s(:or, *children))))
808
833
  end
809
834
 
810
835
  def match_as_hash_element(node, key)
@@ -862,9 +887,10 @@ module RubyNext
862
887
  node = predicates.hash_key(hash_has_key(key, hash), key)
863
888
 
864
889
  keys.reduce(node) do |res, key|
865
- s(:and,
866
- res,
867
- predicates.hash_key(hash_has_key(key, hash), key))
890
+ s(:begin,
891
+ s(:and,
892
+ res,
893
+ predicates.hash_key(hash_has_key(key, hash), key)))
868
894
  end
869
895
  end
870
896
 
@@ -873,9 +899,10 @@ module RubyNext
873
899
  def with_guard(node, guard)
874
900
  return node unless guard
875
901
 
876
- s(:and,
877
- node,
878
- guard.children[0]).then do |expr|
902
+ s(:begin,
903
+ s(:and,
904
+ node,
905
+ guard.children[0])).then do |expr|
879
906
  next expr unless guard.type == :unless_guard
880
907
  s(:send, expr, :!)
881
908
  end
@@ -933,10 +960,10 @@ module RubyNext
933
960
  deconstructed_keys[key] = :"k#{deconstructed_keys.size}"
934
961
  end
935
962
 
936
- # Unparser generates `do .. end` blocks, we want to
963
+ # Unparser generates `do .. end` or `{ ... }` multiline blocks, we want to
937
964
  # have single-line blocks with `{ ... }`.
938
965
  def inline_blocks(source)
939
- source.gsub(/do \|_, __i__\|\n\s*([^\n]+)\n\s*end/, '{ |_, __i__| \1 }')
966
+ source.gsub(/(?:do|{) \|_, __i__\|\n\s*([^\n]+)\n\s*(?:end|})/, '{ |_, __i__| \1 }')
940
967
  end
941
968
  end
942
969
  end