unparser 0.4.9 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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