unparser 0.4.9 → 0.5.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.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/bin/unparser +1 -1
  3. data/lib/unparser.rb +98 -61
  4. data/lib/unparser/ast.rb +0 -1
  5. data/lib/unparser/ast/local_variable_scope.rb +6 -76
  6. data/lib/unparser/buffer.rb +19 -16
  7. data/lib/unparser/cli.rb +26 -39
  8. data/lib/unparser/color.rb +0 -3
  9. data/lib/unparser/comments.rb +0 -26
  10. data/lib/unparser/constants.rb +4 -53
  11. data/lib/unparser/diff.rb +0 -17
  12. data/lib/unparser/dsl.rb +0 -32
  13. data/lib/unparser/emitter.rb +23 -425
  14. data/lib/unparser/emitter/alias.rb +2 -8
  15. data/lib/unparser/emitter/args.rb +45 -0
  16. data/lib/unparser/emitter/argument.rb +8 -166
  17. data/lib/unparser/emitter/array.rb +27 -0
  18. data/lib/unparser/emitter/array_pattern.rb +29 -0
  19. data/lib/unparser/emitter/assignment.rb +36 -127
  20. data/lib/unparser/emitter/begin.rb +9 -84
  21. data/lib/unparser/emitter/binary.rb +7 -20
  22. data/lib/unparser/emitter/block.rb +57 -41
  23. data/lib/unparser/emitter/case.rb +6 -48
  24. data/lib/unparser/emitter/case_guard.rb +27 -0
  25. data/lib/unparser/emitter/case_match.rb +40 -0
  26. data/lib/unparser/emitter/cbase.rb +1 -3
  27. data/lib/unparser/emitter/class.rb +6 -26
  28. data/lib/unparser/emitter/const_pattern.rb +24 -0
  29. data/lib/unparser/emitter/def.rb +7 -51
  30. data/lib/unparser/emitter/defined.rb +2 -12
  31. data/lib/unparser/emitter/dstr.rb +22 -0
  32. data/lib/unparser/emitter/dsym.rb +41 -0
  33. data/lib/unparser/emitter/flipflop.rb +11 -10
  34. data/lib/unparser/emitter/float.rb +29 -0
  35. data/lib/unparser/emitter/flow_modifier.rb +8 -55
  36. data/lib/unparser/emitter/for.rb +5 -19
  37. data/lib/unparser/emitter/hash.rb +74 -0
  38. data/lib/unparser/emitter/hash_pattern.rb +67 -0
  39. data/lib/unparser/emitter/hookexe.rb +5 -11
  40. data/lib/unparser/emitter/if.rb +9 -73
  41. data/lib/unparser/emitter/in_match.rb +21 -0
  42. data/lib/unparser/emitter/in_pattern.rb +34 -0
  43. data/lib/unparser/emitter/index.rb +21 -88
  44. data/lib/unparser/emitter/kwbegin.rb +31 -0
  45. data/lib/unparser/emitter/lambda.rb +0 -8
  46. data/lib/unparser/emitter/masgn.rb +20 -0
  47. data/lib/unparser/emitter/match.rb +3 -17
  48. data/lib/unparser/emitter/match_alt.rb +23 -0
  49. data/lib/unparser/emitter/match_as.rb +21 -0
  50. data/lib/unparser/emitter/match_rest.rb +26 -0
  51. data/lib/unparser/emitter/match_var.rb +19 -0
  52. data/lib/unparser/emitter/mlhs.rb +40 -0
  53. data/lib/unparser/emitter/module.rb +3 -9
  54. data/lib/unparser/emitter/op_assign.rb +12 -27
  55. data/lib/unparser/emitter/pin.rb +19 -0
  56. data/lib/unparser/emitter/primitive.rb +93 -0
  57. data/lib/unparser/emitter/range.rb +35 -0
  58. data/lib/unparser/emitter/regexp.rb +35 -0
  59. data/lib/unparser/emitter/repetition.rb +17 -57
  60. data/lib/unparser/emitter/rescue.rb +1 -97
  61. data/lib/unparser/emitter/root.rb +17 -1
  62. data/lib/unparser/emitter/send.rb +10 -219
  63. data/lib/unparser/emitter/simple.rb +33 -0
  64. data/lib/unparser/emitter/splat.rb +2 -18
  65. data/lib/unparser/emitter/super.rb +1 -29
  66. data/lib/unparser/emitter/undef.rb +1 -9
  67. data/lib/unparser/emitter/variable.rb +1 -31
  68. data/lib/unparser/emitter/xstr.rb +72 -0
  69. data/lib/unparser/emitter/yield.rb +1 -9
  70. data/lib/unparser/generation.rb +250 -0
  71. data/lib/unparser/node_details.rb +21 -0
  72. data/lib/unparser/node_details/send.rb +62 -0
  73. data/lib/unparser/node_helpers.rb +45 -6
  74. data/lib/unparser/validation.rb +37 -35
  75. data/lib/unparser/writer.rb +15 -0
  76. data/lib/unparser/writer/binary.rb +99 -0
  77. data/lib/unparser/writer/dynamic_string.rb +229 -0
  78. data/lib/unparser/writer/resbody.rb +40 -0
  79. data/lib/unparser/writer/rescue.rb +39 -0
  80. data/lib/unparser/writer/send.rb +124 -0
  81. data/lib/unparser/{emitter → writer}/send/attribute_assignment.rb +11 -26
  82. data/lib/unparser/writer/send/binary.rb +27 -0
  83. data/lib/unparser/writer/send/conditional.rb +25 -0
  84. data/lib/unparser/writer/send/regular.rb +33 -0
  85. data/lib/unparser/{emitter → writer}/send/unary.rb +10 -17
  86. metadata +63 -31
  87. data/lib/unparser/emitter/empty.rb +0 -23
  88. data/lib/unparser/emitter/ensure.rb +0 -37
  89. data/lib/unparser/emitter/literal.rb +0 -10
  90. data/lib/unparser/emitter/literal/array.rb +0 -29
  91. data/lib/unparser/emitter/literal/dynamic.rb +0 -53
  92. data/lib/unparser/emitter/literal/dynamic_body.rb +0 -132
  93. data/lib/unparser/emitter/literal/execute_string.rb +0 -38
  94. data/lib/unparser/emitter/literal/hash.rb +0 -156
  95. data/lib/unparser/emitter/literal/primitive.rb +0 -145
  96. data/lib/unparser/emitter/literal/range.rb +0 -36
  97. data/lib/unparser/emitter/literal/regexp.rb +0 -114
  98. data/lib/unparser/emitter/literal/singleton.rb +0 -26
  99. data/lib/unparser/emitter/meta.rb +0 -16
  100. data/lib/unparser/emitter/redo.rb +0 -25
  101. data/lib/unparser/emitter/resbody.rb +0 -76
  102. data/lib/unparser/emitter/retry.rb +0 -25
  103. data/lib/unparser/emitter/send/binary.rb +0 -57
  104. data/lib/unparser/emitter/send/conditional.rb +0 -40
  105. data/lib/unparser/emitter/send/regular.rb +0 -40
  106. data/lib/unparser/preprocessor.rb +0 -159
@@ -4,38 +4,24 @@ module Unparser
4
4
  class Emitter
5
5
  # Emitter for for nodes
6
6
  class For < self
7
- include Terminated
8
-
9
7
  handle :for
10
8
 
11
9
  children :condition, :assignment, :body
12
10
 
13
11
  private
14
12
 
15
- # Perform dispatch
16
- #
17
- # @return [undefined]
18
- #
19
- # @api private
20
- #
21
13
  def dispatch
22
- write(K_FOR, WS)
14
+ write('for ')
23
15
  emit_condition
24
- emit_body
16
+ emit_optional_body(body)
25
17
  k_end
26
18
  end
27
19
 
28
- # Emit assignment
29
- #
30
- # @return [undefined]
31
- #
32
- # @api private
33
- #
34
20
  def emit_condition
35
- visit_plain(condition)
36
- write(WS, K_IN, WS)
21
+ visit(condition)
22
+ write(' in ')
37
23
  visit(assignment)
38
- write(WS, K_DO)
24
+ write(' do')
39
25
  end
40
26
 
41
27
  end # For
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unparser
4
+ class Emitter
5
+ # Emitter for Hash literals
6
+ class Hash < self
7
+ BAREWORD = /\A[A-Za-z_][A-Za-z_0-9]*[?!]?\z/.freeze
8
+
9
+ private_constant(*constants(false))
10
+
11
+ handle :hash
12
+
13
+ def emit_last_argument_hash
14
+ if children.empty?
15
+ write('{}')
16
+ else
17
+ emit_hash_body
18
+ end
19
+ end
20
+
21
+ def emit_heredoc_reminders
22
+ children.each(&method(:emit_heredoc_reminder_member))
23
+ end
24
+
25
+ private
26
+
27
+ def dispatch
28
+ if children.empty?
29
+ write('{}')
30
+ else
31
+ parentheses('{', '}') do
32
+ write(' ')
33
+ emit_hash_body
34
+ write(' ')
35
+ end
36
+ end
37
+ end
38
+
39
+ def emit_heredoc_reminder_member(node)
40
+ emitter(node.children.last).emit_heredoc_reminders
41
+ end
42
+
43
+ def emit_hash_body
44
+ delimited(children, &method(:emit_hash_member))
45
+ end
46
+
47
+ def emit_hash_member(node)
48
+ if n_kwsplat?(node)
49
+ visit(node)
50
+ else
51
+ emit_pair(node)
52
+ end
53
+ end
54
+
55
+ def emit_pair(pair)
56
+ key, value = *pair.children
57
+
58
+ if colon?(key)
59
+ write(key.children.first.to_s, ': ')
60
+ else
61
+ visit(key)
62
+ write(' => ')
63
+ end
64
+
65
+ visit(value)
66
+ end
67
+
68
+ def colon?(key)
69
+ n_sym?(key) && BAREWORD.match?(key.children.first)
70
+ end
71
+
72
+ end # Hash
73
+ end # Emitter
74
+ end # Unparser
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unparser
4
+ class Emitter
5
+ # Emitter for hash patterns
6
+ class HashPattern < self
7
+
8
+ handle :hash_pattern
9
+
10
+ def emit_const_pattern
11
+ parentheses do
12
+ emit_hash_body
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def dispatch
19
+ parentheses('{', '}') do
20
+ emit_hash_body
21
+ end
22
+ end
23
+
24
+ def emit_hash_body
25
+ delimited(children, &method(:emit_member))
26
+ end
27
+
28
+ def emit_member(node)
29
+ case node.type
30
+ when :pair
31
+ emit_pair(node)
32
+ when :match_var
33
+ emit_match_var(node)
34
+ when :match_rest
35
+ writer_with(MatchRest, node).emit_hash_pattern
36
+ else
37
+ visit(node)
38
+ end
39
+ end
40
+
41
+ def emit_match_var(node)
42
+ write_symbol_body(node.children.first)
43
+ write(':')
44
+ end
45
+
46
+ def emit_pair(node)
47
+ key, value = node.children
48
+
49
+ if n_sym?(key)
50
+ write_symbol_body(key.children.first)
51
+ else
52
+ visit(s(:dstr, *key))
53
+ end
54
+
55
+ write(':')
56
+
57
+ ws
58
+
59
+ visit(value)
60
+ end
61
+
62
+ def write_symbol_body(symbol)
63
+ write(symbol.inspect[1..-1])
64
+ end
65
+ end # Pin
66
+ end # Emitter
67
+ end # Unparser
@@ -6,8 +6,8 @@ module Unparser
6
6
  class Hookexe < self
7
7
 
8
8
  MAP = {
9
- preexe: K_PREEXE,
10
- postexe: K_POSTEXE
9
+ preexe: 'BEGIN',
10
+ postexe: 'END'
11
11
  }.freeze
12
12
 
13
13
  handle(*MAP.keys)
@@ -16,16 +16,10 @@ module Unparser
16
16
 
17
17
  private
18
18
 
19
- # Perfrom dispatch
20
- #
21
- # @return [undefined]
22
- #
23
- # @api private
24
- #
25
19
  def dispatch
26
- write(MAP.fetch(node.type), WS)
27
- parentheses(*BRACKETS_CURLY) do
28
- emit_body
20
+ write(MAP.fetch(node.type), ' ')
21
+ parentheses('{', '}') do
22
+ emit_body(body)
29
23
  end
30
24
  end
31
25
 
@@ -3,25 +3,13 @@
3
3
  module Unparser
4
4
  class Emitter
5
5
  # Emitter if nodes
6
- #
7
- # ignore :reek:RepeatedConditional
8
6
  class If < self
9
7
  handle :if
10
8
 
11
9
  children :condition, :if_branch, :else_branch
12
10
 
13
- def terminated?
14
- !postcondition?
15
- end
16
-
17
11
  private
18
12
 
19
- # Perform dispatch
20
- #
21
- # @return [undefined]
22
- #
23
- # @api private
24
- #
25
13
  def dispatch
26
14
  if postcondition?
27
15
  emit_postcondition
@@ -30,105 +18,53 @@ module Unparser
30
18
  end
31
19
  end
32
20
 
33
- # Test for postcondition
34
- #
35
- # @return [Boolean]
36
- #
37
- # @api private
38
- #
39
21
  def postcondition?
40
22
  return false unless if_branch.nil? ^ else_branch.nil?
41
23
 
42
24
  body = if_branch || else_branch
43
25
 
44
- local_variable_scope.first_assignment_in_body_and_used_in_condition?(body, condition)
26
+ local_variable_scope.first_assignment_in?(body, condition)
45
27
  end
46
28
 
47
- # Emit in postcondition style
48
- #
49
- # @return [undefined]
50
- #
51
- # @api private
52
- #
53
29
  def emit_postcondition
54
- visit_plain(if_branch || else_branch)
55
- write(WS, keyword, WS)
30
+ visit(if_branch || else_branch)
31
+ write(' ', keyword, ' ')
56
32
  emit_condition
57
33
  end
58
34
 
59
- # Emit in normal style
60
- #
61
- # @return [undefined]
62
- #
63
- # @api private
64
- #
65
35
  def emit_normal
66
- write(keyword, WS)
36
+ write(keyword, ' ')
67
37
  emit_condition
68
38
  emit_if_branch
69
39
  emit_else_branch
70
40
  k_end
71
41
  end
72
42
 
73
- # Test if AST can be emitted as unless
74
- #
75
- # @return [Boolean]
76
- #
77
- # @api private
78
- #
79
43
  def unless?
80
44
  !if_branch && else_branch
81
45
  end
82
46
 
83
- # Return keyword
84
- #
85
- # @return [String]
86
- #
87
- # @api private
88
- #
89
47
  def keyword
90
- unless? ? K_UNLESS : K_IF
48
+ unless? ? 'unless' : 'if'
91
49
  end
92
50
 
93
- # Emit condition
94
- #
95
- # @return [undefined]
96
- #
97
- # @api private
98
- #
99
51
  def emit_condition
100
- if condition.type.equal?(:match_current_line)
101
- visit_plain(condition)
102
- else
103
- visit(condition)
104
- end
52
+ visit(condition)
105
53
  end
106
54
 
107
- # Emit if branch
108
- #
109
- # @return [undefined]
110
- #
111
- # @api private
112
- #
113
55
  def emit_if_branch
114
56
  if if_branch
115
- visit_indented(if_branch)
57
+ emit_body(if_branch)
116
58
  end
117
59
 
118
60
  nl if !if_branch && !else_branch
119
61
  end
120
62
 
121
- # Emit else branch
122
- #
123
- # @return [undefined]
124
- #
125
- # @api private
126
- #
127
63
  def emit_else_branch
128
64
  return unless else_branch
129
65
 
130
- write(K_ELSE) unless unless?
131
- visit_indented(else_branch)
66
+ write('else') unless unless?
67
+ emit_body(else_branch)
132
68
  end
133
69
 
134
70
  end # If
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unparser
4
+ class Emitter
5
+ # Emitter for in pattern nodes
6
+ class InMatch < self
7
+
8
+ handle :in_match
9
+
10
+ children :target, :pattern
11
+
12
+ private
13
+
14
+ def dispatch
15
+ visit(target)
16
+ write(' in ')
17
+ visit(pattern)
18
+ end
19
+ end # InMatch
20
+ end # Emitter
21
+ end # Unparser
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unparser
4
+ class Emitter
5
+ # Emitter for in pattern nodes
6
+ class InPattern < self
7
+
8
+ handle :in_pattern
9
+
10
+ children :target, :unless_guard, :branch, :else_branch
11
+
12
+ private
13
+
14
+ def dispatch
15
+ write('in')
16
+
17
+ ws
18
+
19
+ visit(target)
20
+
21
+ if unless_guard
22
+ ws
23
+ visit(unless_guard)
24
+ end
25
+
26
+ if branch
27
+ ws
28
+ write('then')
29
+ emit_body(branch)
30
+ end
31
+ end
32
+ end # InPattern
33
+ end # Emitter
34
+ end # Unparser
@@ -3,61 +3,29 @@
3
3
  module Unparser
4
4
  class Emitter
5
5
  # Emitter for send to index references
6
- #
7
- # ignore :reek:RepeatedConditional
8
6
  class Index < self
9
7
 
10
- # Perform dispatch
11
- #
12
- # @return [undefined]
13
- #
14
- # @api private
15
- #
8
+ private
9
+
16
10
  def dispatch
17
11
  emit_receiver
18
12
  emit_operation
19
13
  end
20
14
 
21
- private
22
-
23
- # Emit receiver
24
- #
25
- # @return [undefined]
26
- #
27
- # @api private
28
- #
29
15
  def emit_receiver
30
16
  visit(first_child)
31
17
  end
32
18
 
33
- # Test for mlhs
34
- #
35
- # @return [Boolean]
36
- #
37
- # @api private
38
- #
39
- def mlhs?
40
- parent_type.equal?(:mlhs)
41
- end
42
-
43
19
  class Reference < self
44
- include Terminated
45
-
46
20
  define_group(:indices, 1..-1)
47
21
 
48
22
  handle :index
49
23
 
50
24
  private
51
25
 
52
- # Emit arguments
53
- #
54
- # @return [undefined]
55
- #
56
- # @api private
57
- #
58
26
  def emit_operation
59
- parentheses(*BRACKETS_SQUARE) do
60
- delimited_plain(indices)
27
+ parentheses('[', ']') do
28
+ delimited(indices)
61
29
  end
62
30
  end
63
31
  end # Reference
@@ -70,65 +38,30 @@ module Unparser
70
38
  VALUE_RANGE = (1..-2).freeze
71
39
  NO_VALUE_PARENT = IceNine.deep_freeze(%i[and_asgn op_asgn or_asgn].to_set)
72
40
 
73
- # Test if assign will be emitted terminated
74
- #
75
- # @return [Boolean]
76
- #
77
- # @api private
78
- #
79
- def terminated?
80
- !emit_value?
81
- end
82
-
83
- private
41
+ private_constant(*constants(false))
84
42
 
85
- # Emit arguments
86
- #
87
- # @return [undefined]
88
- #
89
- # @api private
90
- #
91
- def emit_operation
92
- parentheses(*BRACKETS_SQUARE) do
93
- delimited_plain(indices)
94
- end
95
-
96
- if emit_value?
97
- write(WS, T_ASN, WS)
98
- visit(children.last)
99
- end
43
+ def emit_heredoc_reminders
44
+ emitter(children.last).emit_heredoc_reminders
100
45
  end
101
46
 
102
- # The indices
103
- #
104
- # @return [Array<Parser::AST::Node>]
105
- #
106
- def indices
107
- if emit_value?
108
- children[VALUE_RANGE]
109
- else
110
- children.drop(1)
111
- end
47
+ def dispatch
48
+ emit_receiver
49
+ emit_operation(children[VALUE_RANGE])
50
+ write(' = ')
51
+ visit(children.last)
112
52
  end
113
53
 
114
- # Test if value should be emitted
115
- #
116
- # @return [Boolean]
117
- #
118
- # @api private
119
- #
120
- def emit_value?
121
- !mlhs? && !no_value_parent?
54
+ def emit_mlhs
55
+ emit_receiver
56
+ emit_operation(children.drop(1))
122
57
  end
123
58
 
124
- # Test for no value parent
125
- #
126
- # @return [Boolean]
127
- #
128
- # @api private
129
- #
130
- def no_value_parent?
131
- NO_VALUE_PARENT.include?(parent_type)
59
+ private
60
+
61
+ def emit_operation(indices)
62
+ parentheses('[', ']') do
63
+ delimited(indices)
64
+ end
132
65
  end
133
66
  end # Assign
134
67
  end # Index