unparser 0.6.5 → 0.8.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/README.md +11 -6
- data/bin/unparser +1 -1
- data/lib/unparser/adamantium.rb +3 -1
- data/lib/unparser/anima.rb +11 -0
- data/lib/unparser/ast/local_variable_scope.rb +28 -25
- data/lib/unparser/ast.rb +18 -22
- data/lib/unparser/buffer.rb +43 -15
- data/lib/unparser/cli.rb +30 -7
- data/lib/unparser/color.rb +5 -0
- data/lib/unparser/either.rb +6 -6
- data/lib/unparser/emitter/args.rb +5 -1
- data/lib/unparser/emitter/argument.rb +6 -4
- data/lib/unparser/emitter/array.rb +0 -4
- data/lib/unparser/emitter/array_pattern.rb +1 -9
- data/lib/unparser/emitter/assignment.rb +17 -8
- data/lib/unparser/emitter/begin.rb +0 -6
- data/lib/unparser/emitter/binary.rb +1 -1
- data/lib/unparser/emitter/block.rb +13 -6
- data/lib/unparser/emitter/def.rb +1 -1
- data/lib/unparser/emitter/dstr.rb +6 -5
- data/lib/unparser/emitter/dsym.rb +1 -1
- data/lib/unparser/emitter/ensure.rb +16 -0
- data/lib/unparser/emitter/flipflop.rb +7 -2
- data/lib/unparser/emitter/flow_modifier.rb +1 -7
- data/lib/unparser/emitter/for.rb +1 -1
- data/lib/unparser/emitter/hash.rb +0 -16
- data/lib/unparser/emitter/hash_pattern.rb +1 -1
- data/lib/unparser/emitter/in_pattern.rb +9 -1
- data/lib/unparser/emitter/index.rb +0 -4
- data/lib/unparser/emitter/kwbegin.rb +1 -1
- data/lib/unparser/emitter/match_pattern.rb +7 -11
- data/lib/unparser/emitter/match_pattern_p.rb +6 -1
- data/lib/unparser/emitter/mlhs.rb +7 -1
- data/lib/unparser/emitter/op_assign.rb +0 -5
- data/lib/unparser/emitter/pair.rb +31 -5
- data/lib/unparser/emitter/primitive.rb +19 -6
- data/lib/unparser/emitter/range.rb +23 -2
- data/lib/unparser/emitter/regexp.rb +5 -17
- data/lib/unparser/emitter/rescue.rb +7 -1
- data/lib/unparser/emitter/root.rb +2 -9
- data/lib/unparser/emitter/send.rb +1 -5
- data/lib/unparser/emitter/string.rb +31 -0
- data/lib/unparser/emitter/xstr.rb +8 -1
- data/lib/unparser/emitter.rb +9 -10
- data/lib/unparser/generation.rb +33 -29
- data/lib/unparser/node_details/send.rb +4 -3
- data/lib/unparser/node_details.rb +1 -0
- data/lib/unparser/node_helpers.rb +19 -9
- data/lib/unparser/util.rb +23 -0
- data/lib/unparser/validation.rb +70 -28
- data/lib/unparser/writer/array.rb +51 -0
- data/lib/unparser/writer/binary.rb +8 -4
- data/lib/unparser/writer/dynamic_string.rb +127 -146
- data/lib/unparser/writer/regexp.rb +101 -0
- data/lib/unparser/writer/resbody.rb +37 -3
- data/lib/unparser/writer/rescue.rb +3 -7
- data/lib/unparser/writer/send/unary.rb +9 -4
- data/lib/unparser/writer/send.rb +8 -14
- data/lib/unparser/writer.rb +31 -1
- data/lib/unparser.rb +149 -38
- metadata +38 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e0e776dd7b47efb62b8ad18d7262d247362944f28ea67edb7e518d8a94c74649
|
|
4
|
+
data.tar.gz: 759ec6fb240c4c62835bd8c789877fc26fc974563d2566687a63b2c0dec1072f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 11fe99943d2575e00ca2fc150a78cad1f2f830b3249f3692f473da7e520775fc9423b254fb2f7613e4b6811f03dd3d2af0d4bba1d0f2f143e048ab65281771ff
|
|
7
|
+
data.tar.gz: f08db4117aa2ebba9c5ac7a9e057ca7ddc9fc0613170752ac10cc7515058f491fe756b880db73629e2e7a8328cc979872b4c682197c061de39da52a44796587f
|
data/README.md
CHANGED
|
@@ -10,13 +10,13 @@ The following constraints apply:
|
|
|
10
10
|
|
|
11
11
|
* No support for macruby extensions
|
|
12
12
|
* Only support for the [modern AST](https://github.com/whitequark/parser/#usage) format
|
|
13
|
-
* Only support for Ruby >= 2
|
|
13
|
+
* Only support for Ruby >= 3.2
|
|
14
14
|
|
|
15
15
|
Notable Users:
|
|
16
16
|
|
|
17
17
|
* [mutant](https://github.com/mbj/mutant) - Code review engine via mutation testing.
|
|
18
18
|
* [ruby-next](https://github.com/ruby-next/ruby-next) - Ruby Syntax Backports.
|
|
19
|
-
*
|
|
19
|
+
* Many other [reverse-dependencies](https://rubygems.org/gems/unparser/reverse_dependencies).
|
|
20
20
|
|
|
21
21
|
(if you want your tool to be mentioned here please PR the addition with a TLDR of your use case).
|
|
22
22
|
|
|
@@ -44,9 +44,9 @@ To preserve the comments from the source:
|
|
|
44
44
|
require 'parser/current'
|
|
45
45
|
require 'unparser'
|
|
46
46
|
|
|
47
|
-
ast, comments = Unparser.parse_with_comments('your(ruby(code)) # with comments')
|
|
47
|
+
ast, comments = Unparser.parser.parse_with_comments(Unparser.buffer('your(ruby(code)) # with comments'))
|
|
48
48
|
|
|
49
|
-
Unparser.unparse(ast, comments) # => 'your(ruby(code)) # with comments'
|
|
49
|
+
Unparser.unparse(ast, comments: comments) # => 'your(ruby(code)) # with comments'
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
Passing in manually constructed AST:
|
|
@@ -114,7 +114,7 @@ Unparser currently successfully round trips almost all ruby code around. Using R
|
|
|
114
114
|
If there is a non round trippable example that is NOT subjected to known [Limitations](#limitations).
|
|
115
115
|
please report a bug.
|
|
116
116
|
|
|
117
|
-
On CI unparser is currently tested against rubyspec with minor [excludes](https://github.com/mbj/unparser/blob/
|
|
117
|
+
On CI unparser is currently tested against rubyspec with minor [excludes](https://github.com/mbj/unparser/blob/main/spec/integrations.yml).
|
|
118
118
|
|
|
119
119
|
Limitations:
|
|
120
120
|
------------
|
|
@@ -187,10 +187,15 @@ Contributing
|
|
|
187
187
|
* Make your feature addition or bug fix.
|
|
188
188
|
* Add tests for it. This is important so I don't break it in a
|
|
189
189
|
future version unintentionally.
|
|
190
|
-
* Commit, do not mess with
|
|
190
|
+
* Commit, do not mess with version
|
|
191
191
|
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
|
192
192
|
* Send me a pull request. Bonus points for topic branches.
|
|
193
193
|
|
|
194
|
+
Known Users
|
|
195
|
+
-------------
|
|
196
|
+
|
|
197
|
+
* [RailsRocket](https://www.railsrocket.app) - A no-code app builder that creates Rails apps
|
|
198
|
+
|
|
194
199
|
License
|
|
195
200
|
-------
|
|
196
201
|
|
data/bin/unparser
CHANGED
data/lib/unparser/adamantium.rb
CHANGED
data/lib/unparser/anima.rb
CHANGED
|
@@ -134,14 +134,25 @@ module Unparser
|
|
|
134
134
|
# @param [Class, Module] scope
|
|
135
135
|
#
|
|
136
136
|
# @return [undefined]
|
|
137
|
+
#
|
|
138
|
+
# mutant:disable
|
|
137
139
|
def included(descendant)
|
|
138
140
|
descendant.instance_exec(self, attribute_names) do |anima, names|
|
|
139
141
|
# Define anima method
|
|
142
|
+
|
|
143
|
+
class << self
|
|
144
|
+
undef_method(:anima) if method_defined?(:anima)
|
|
145
|
+
end
|
|
146
|
+
|
|
140
147
|
define_singleton_method(:anima) { anima }
|
|
141
148
|
|
|
142
149
|
# Define instance methods
|
|
143
150
|
include InstanceMethods
|
|
144
151
|
|
|
152
|
+
names.each do |name|
|
|
153
|
+
undef_method(name) if method_defined?(name)
|
|
154
|
+
end
|
|
155
|
+
|
|
145
156
|
# Define attribute readers
|
|
146
157
|
attr_reader(*names)
|
|
147
158
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Unparser
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
class AST
|
|
6
5
|
# Calculated local variable scope for a given node
|
|
7
6
|
class LocalVariableScope
|
|
8
|
-
include
|
|
7
|
+
include Adamantium, Anima.new(:static_local_variables, :node)
|
|
9
8
|
|
|
10
9
|
# Initialize object
|
|
11
10
|
#
|
|
@@ -13,15 +12,18 @@ module Unparser
|
|
|
13
12
|
#
|
|
14
13
|
# @return [undefined]
|
|
15
14
|
#
|
|
16
|
-
#
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
# mutant:disable
|
|
16
|
+
def initialize(*arguments)
|
|
17
|
+
super
|
|
18
|
+
|
|
19
19
|
items = []
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
|
|
21
|
+
LocalVariableScopeEnumerator.each(
|
|
22
|
+
node: node,
|
|
23
|
+
stack: static_local_variables.dup
|
|
24
|
+
) { |*scope| items << scope }
|
|
25
|
+
|
|
23
26
|
@items = items
|
|
24
|
-
super(node)
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
# Test if local variable was first at given assignment
|
|
@@ -54,6 +56,15 @@ module Unparser
|
|
|
54
56
|
end
|
|
55
57
|
end
|
|
56
58
|
|
|
59
|
+
# mutant:disable
|
|
60
|
+
def local_variables_for_node(needle)
|
|
61
|
+
@items.each do |node, current|
|
|
62
|
+
return current if node.equal?(needle)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
Set.new
|
|
66
|
+
end
|
|
67
|
+
|
|
57
68
|
# Test if local variables where first assigned in body and read by conditional
|
|
58
69
|
#
|
|
59
70
|
# @param [Parser::AST::Node] body
|
|
@@ -91,21 +102,13 @@ module Unparser
|
|
|
91
102
|
#
|
|
92
103
|
# @api private
|
|
93
104
|
#
|
|
94
|
-
def initialize
|
|
95
|
-
@stack = [
|
|
105
|
+
def initialize(stack:)
|
|
106
|
+
@stack = [stack]
|
|
96
107
|
end
|
|
97
108
|
|
|
98
109
|
# Enumerate each node with its local variable scope
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
#
|
|
102
|
-
# @return [self]
|
|
103
|
-
#
|
|
104
|
-
# @api private
|
|
105
|
-
#
|
|
106
|
-
def self.each(node, &block)
|
|
107
|
-
new.each(node, &block)
|
|
108
|
-
self
|
|
110
|
+
def self.each(node:, stack:, &block)
|
|
111
|
+
new(stack: stack).each(node: node, &block)
|
|
109
112
|
end
|
|
110
113
|
|
|
111
114
|
# Enumerate local variable scope scope
|
|
@@ -118,7 +121,7 @@ module Unparser
|
|
|
118
121
|
#
|
|
119
122
|
# @api private
|
|
120
123
|
#
|
|
121
|
-
def each(node
|
|
124
|
+
def each(node:, &block)
|
|
122
125
|
visit(node, &block)
|
|
123
126
|
end
|
|
124
127
|
|
|
@@ -133,7 +136,7 @@ module Unparser
|
|
|
133
136
|
enter(node)
|
|
134
137
|
yield node, current.dup, before
|
|
135
138
|
node.children.each do |child|
|
|
136
|
-
visit(child, &block) if child.
|
|
139
|
+
visit(child, &block) if child.instance_of?(Parser::AST::Node)
|
|
137
140
|
end
|
|
138
141
|
leave(node)
|
|
139
142
|
end
|
|
@@ -143,7 +146,7 @@ module Unparser
|
|
|
143
146
|
when *RESET_NODES
|
|
144
147
|
push_reset
|
|
145
148
|
when ASSIGN_NODES
|
|
146
|
-
|
|
149
|
+
value = node.children.first and define(value)
|
|
147
150
|
when *INHERIT_NODES
|
|
148
151
|
push_inherit
|
|
149
152
|
end
|
data/lib/unparser/ast.rb
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
module Unparser
|
|
4
4
|
# Namespace for AST processing tools
|
|
5
|
-
|
|
5
|
+
class AST
|
|
6
|
+
include Anima.new(:comments, :explicit_encoding, :node, :static_local_variables)
|
|
7
|
+
|
|
6
8
|
FIRST_CHILD = ->(node) { node.children.first }.freeze
|
|
7
|
-
TAUTOLOGY = ->(_node) { true }.freeze
|
|
8
9
|
|
|
9
10
|
RESET_NODES = %i[module class sclass def defs].freeze
|
|
10
11
|
INHERIT_NODES = [:block].freeze
|
|
@@ -16,12 +17,22 @@ module Unparser
|
|
|
16
17
|
arg
|
|
17
18
|
kwarg
|
|
18
19
|
kwoptarg
|
|
20
|
+
kwrestarg
|
|
19
21
|
lvasgn
|
|
20
22
|
optarg
|
|
21
|
-
procarg0
|
|
22
23
|
restarg
|
|
23
24
|
].to_set.freeze
|
|
24
25
|
|
|
26
|
+
# mutant:disable
|
|
27
|
+
def self.from_node(node:)
|
|
28
|
+
new(
|
|
29
|
+
comments: EMPTY_ARRAY,
|
|
30
|
+
explicit_encoding: nil,
|
|
31
|
+
node:,
|
|
32
|
+
static_local_variables: Set.new
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
|
|
25
36
|
# Test for local variable inherited scope reset
|
|
26
37
|
#
|
|
27
38
|
# @param [Parser::AST::Node] node
|
|
@@ -69,6 +80,7 @@ module Unparser
|
|
|
69
80
|
#
|
|
70
81
|
# @api private
|
|
71
82
|
#
|
|
83
|
+
# mutant:disable
|
|
72
84
|
def self.local_variable_reads(node)
|
|
73
85
|
Enumerator.new(
|
|
74
86
|
node,
|
|
@@ -80,19 +92,6 @@ module Unparser
|
|
|
80
92
|
class Enumerator
|
|
81
93
|
include Adamantium, Concord.new(:node, :controller), Enumerable
|
|
82
94
|
|
|
83
|
-
# Return new instance
|
|
84
|
-
#
|
|
85
|
-
# @param [Parser::AST::Node] node
|
|
86
|
-
# @param [#call(node)] controller
|
|
87
|
-
#
|
|
88
|
-
# @return [Enumerator]
|
|
89
|
-
#
|
|
90
|
-
# @api private
|
|
91
|
-
#
|
|
92
|
-
def self.new(node, controller = TAUTOLOGY)
|
|
93
|
-
super
|
|
94
|
-
end
|
|
95
|
-
|
|
96
95
|
# Return each node
|
|
97
96
|
#
|
|
98
97
|
# @return [Enumerator<Parser::AST::Node>]
|
|
@@ -103,8 +102,8 @@ module Unparser
|
|
|
103
102
|
#
|
|
104
103
|
# @api private
|
|
105
104
|
#
|
|
106
|
-
def each(&
|
|
107
|
-
Walker.call(node, controller, &
|
|
105
|
+
def each(&)
|
|
106
|
+
Walker.call(node, controller, &)
|
|
108
107
|
end
|
|
109
108
|
|
|
110
109
|
# Return nodes selected by types
|
|
@@ -168,13 +167,10 @@ module Unparser
|
|
|
168
167
|
#
|
|
169
168
|
# @param [Parser::AST::Node] node
|
|
170
169
|
#
|
|
171
|
-
# @return [self]
|
|
172
|
-
#
|
|
173
170
|
# @api private
|
|
174
171
|
#
|
|
175
|
-
def self.call(node, controller
|
|
172
|
+
def self.call(node, controller, &block)
|
|
176
173
|
new(block, controller).call(node)
|
|
177
|
-
self
|
|
178
174
|
end
|
|
179
175
|
|
|
180
176
|
# Call walker with node
|
data/lib/unparser/buffer.rb
CHANGED
|
@@ -14,8 +14,10 @@ module Unparser
|
|
|
14
14
|
# @api private
|
|
15
15
|
#
|
|
16
16
|
def initialize
|
|
17
|
-
@content
|
|
18
|
-
@
|
|
17
|
+
@content = +''
|
|
18
|
+
@heredocs = []
|
|
19
|
+
@indent = 0
|
|
20
|
+
@no_nl = true
|
|
19
21
|
end
|
|
20
22
|
|
|
21
23
|
# Append string
|
|
@@ -34,6 +36,13 @@ module Unparser
|
|
|
34
36
|
self
|
|
35
37
|
end
|
|
36
38
|
|
|
39
|
+
# Push to heredoc stack
|
|
40
|
+
#
|
|
41
|
+
# @param [String] heredoc
|
|
42
|
+
def push_heredoc(heredoc)
|
|
43
|
+
@heredocs << heredoc
|
|
44
|
+
end
|
|
45
|
+
|
|
37
46
|
# Append a string without an indentation prefix
|
|
38
47
|
#
|
|
39
48
|
# @param [String] string
|
|
@@ -44,7 +53,6 @@ module Unparser
|
|
|
44
53
|
#
|
|
45
54
|
def append_without_prefix(string)
|
|
46
55
|
write(string)
|
|
47
|
-
self
|
|
48
56
|
end
|
|
49
57
|
|
|
50
58
|
# Increase indent
|
|
@@ -69,6 +77,10 @@ module Unparser
|
|
|
69
77
|
self
|
|
70
78
|
end
|
|
71
79
|
|
|
80
|
+
def ensure_nl
|
|
81
|
+
nl unless fresh_line?
|
|
82
|
+
end
|
|
83
|
+
|
|
72
84
|
# Write newline
|
|
73
85
|
#
|
|
74
86
|
# @return [self]
|
|
@@ -76,10 +88,29 @@ module Unparser
|
|
|
76
88
|
# @api private
|
|
77
89
|
#
|
|
78
90
|
def nl
|
|
91
|
+
@no_nl = false
|
|
79
92
|
write(NL)
|
|
93
|
+
flush_heredocs
|
|
80
94
|
self
|
|
81
95
|
end
|
|
82
96
|
|
|
97
|
+
# Write final newline
|
|
98
|
+
def final_newline
|
|
99
|
+
return if fresh_line? || @no_nl
|
|
100
|
+
|
|
101
|
+
write(NL)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def nl_flush_heredocs
|
|
105
|
+
return if @heredocs.empty?
|
|
106
|
+
|
|
107
|
+
if fresh_line?
|
|
108
|
+
flush_heredocs
|
|
109
|
+
else
|
|
110
|
+
nl
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
83
114
|
def root_indent
|
|
84
115
|
before = @indent
|
|
85
116
|
@indent = 0
|
|
@@ -107,18 +138,6 @@ module Unparser
|
|
|
107
138
|
@content.dup.freeze
|
|
108
139
|
end
|
|
109
140
|
|
|
110
|
-
# Capture the content written to the buffer within the block
|
|
111
|
-
#
|
|
112
|
-
# @return [String]
|
|
113
|
-
#
|
|
114
|
-
# @api private
|
|
115
|
-
#
|
|
116
|
-
def capture_content
|
|
117
|
-
size_before = content.size
|
|
118
|
-
yield
|
|
119
|
-
content[size_before..]
|
|
120
|
-
end
|
|
121
|
-
|
|
122
141
|
# Write raw fragment to buffer
|
|
123
142
|
#
|
|
124
143
|
# Does not do indentation logic.
|
|
@@ -131,6 +150,10 @@ module Unparser
|
|
|
131
150
|
self
|
|
132
151
|
end
|
|
133
152
|
|
|
153
|
+
def write_encoding(encoding)
|
|
154
|
+
write("# -*- encoding: #{encoding} -*-\n")
|
|
155
|
+
end
|
|
156
|
+
|
|
134
157
|
private
|
|
135
158
|
|
|
136
159
|
INDENT_SPACE = ' '.freeze
|
|
@@ -139,5 +162,10 @@ module Unparser
|
|
|
139
162
|
write(INDENT_SPACE * @indent)
|
|
140
163
|
end
|
|
141
164
|
|
|
165
|
+
def flush_heredocs
|
|
166
|
+
@heredocs.each(&public_method(:write))
|
|
167
|
+
@heredocs = []
|
|
168
|
+
end
|
|
169
|
+
|
|
142
170
|
end # Buffer
|
|
143
171
|
end # Unparser
|
data/lib/unparser/cli.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'pathname'
|
|
4
|
+
|
|
3
5
|
module Unparser
|
|
4
6
|
# Unparser CLI implementation
|
|
5
7
|
class CLI
|
|
@@ -60,6 +62,7 @@ module Unparser
|
|
|
60
62
|
#
|
|
61
63
|
# @api private
|
|
62
64
|
#
|
|
65
|
+
# mutant:disable
|
|
63
66
|
def self.run(*arguments)
|
|
64
67
|
new(*arguments).exit_status
|
|
65
68
|
end
|
|
@@ -71,15 +74,17 @@ module Unparser
|
|
|
71
74
|
# @return [undefined]
|
|
72
75
|
#
|
|
73
76
|
# @api private
|
|
77
|
+
# mutant:disable
|
|
74
78
|
def initialize(arguments)
|
|
75
79
|
@ignore = Set.new
|
|
76
80
|
@targets = []
|
|
77
81
|
|
|
78
|
-
@fail_fast
|
|
79
|
-
@start_with
|
|
80
|
-
@success
|
|
81
|
-
@validation
|
|
82
|
-
@verbose
|
|
82
|
+
@fail_fast = false
|
|
83
|
+
@start_with = nil
|
|
84
|
+
@success = true
|
|
85
|
+
@validation = :validation
|
|
86
|
+
@verbose = false
|
|
87
|
+
@ignore_original_syntax_error = false
|
|
83
88
|
|
|
84
89
|
opts = OptionParser.new do |builder|
|
|
85
90
|
add_options(builder)
|
|
@@ -98,6 +103,7 @@ module Unparser
|
|
|
98
103
|
#
|
|
99
104
|
# @api private
|
|
100
105
|
#
|
|
106
|
+
# mutant:disable
|
|
101
107
|
# rubocop:disable Metrics/MethodLength
|
|
102
108
|
def add_options(builder)
|
|
103
109
|
builder.banner = 'usage: unparse [options] FILE [FILE]'
|
|
@@ -114,6 +120,9 @@ module Unparser
|
|
|
114
120
|
builder.on('-l', '--literal') do
|
|
115
121
|
@validation = :literal_validation
|
|
116
122
|
end
|
|
123
|
+
builder.on('--ignore-original-syntax-error') do
|
|
124
|
+
@ignore_original_syntax_error = true
|
|
125
|
+
end
|
|
117
126
|
builder.on('--ignore FILE') do |file|
|
|
118
127
|
@ignore.merge(targets(file))
|
|
119
128
|
end
|
|
@@ -129,6 +138,7 @@ module Unparser
|
|
|
129
138
|
#
|
|
130
139
|
# @api private
|
|
131
140
|
#
|
|
141
|
+
# mutant:disable
|
|
132
142
|
def exit_status
|
|
133
143
|
effective_targets.each do |target|
|
|
134
144
|
process_target(target)
|
|
@@ -140,11 +150,15 @@ module Unparser
|
|
|
140
150
|
|
|
141
151
|
private
|
|
142
152
|
|
|
153
|
+
# mutant:disable
|
|
143
154
|
def process_target(target)
|
|
144
155
|
validation = target.public_send(@validation)
|
|
145
156
|
if validation.success?
|
|
146
157
|
puts validation.report if @verbose
|
|
147
158
|
puts "Success: #{validation.identification}"
|
|
159
|
+
elsif ignore_original_syntax_error?(validation)
|
|
160
|
+
exception = validation.original_node.from_left
|
|
161
|
+
puts "#{exception.class}: #{validation.identification} #{exception}"
|
|
148
162
|
else
|
|
149
163
|
puts validation.report
|
|
150
164
|
puts "Error: #{validation.identification}"
|
|
@@ -152,6 +166,14 @@ module Unparser
|
|
|
152
166
|
end
|
|
153
167
|
end
|
|
154
168
|
|
|
169
|
+
# mutant:disable
|
|
170
|
+
def ignore_original_syntax_error?(validation)
|
|
171
|
+
@ignore_original_syntax_error && validation.original_node.from_left do
|
|
172
|
+
nil
|
|
173
|
+
end.instance_of?(Parser::SyntaxError)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# mutant:disable
|
|
155
177
|
def effective_targets
|
|
156
178
|
if @start_with
|
|
157
179
|
reject = true
|
|
@@ -167,13 +189,14 @@ module Unparser
|
|
|
167
189
|
end.reject(&@ignore.method(:include?))
|
|
168
190
|
end
|
|
169
191
|
|
|
192
|
+
# mutant:disable
|
|
170
193
|
def targets(file_name)
|
|
171
194
|
if File.directory?(file_name)
|
|
172
|
-
Dir.glob(File.join(file_name, '**/*.rb'))
|
|
195
|
+
Dir.glob(File.join(file_name, '**/*.rb'))
|
|
173
196
|
elsif File.file?(file_name)
|
|
174
197
|
[file_name]
|
|
175
198
|
else
|
|
176
|
-
Dir.glob(file_name)
|
|
199
|
+
Dir.glob(file_name)
|
|
177
200
|
end.map { |file| Target::Path.new(Pathname.new(file)) }
|
|
178
201
|
end
|
|
179
202
|
end # CLI
|
data/lib/unparser/color.rb
CHANGED
|
@@ -28,7 +28,12 @@ module Unparser
|
|
|
28
28
|
|
|
29
29
|
private
|
|
30
30
|
|
|
31
|
+
# Well rubocop you are static so you do not have a clue here ;)
|
|
32
|
+
# rubocop:disable Style/RedundantInitialize
|
|
33
|
+
# rubocop:disable Lint/MissingSuper
|
|
31
34
|
def initialize; end
|
|
35
|
+
# rubocop:enable Style/RedundantInitialize
|
|
36
|
+
# rubocop:enable Lint/MissingSuper
|
|
32
37
|
|
|
33
38
|
end.new
|
|
34
39
|
|
data/lib/unparser/either.rb
CHANGED
|
@@ -54,15 +54,15 @@ module Unparser
|
|
|
54
54
|
# Evaluate functor block
|
|
55
55
|
#
|
|
56
56
|
# @return [Either::Left<Object>]
|
|
57
|
-
def fmap(&
|
|
58
|
-
require_block(&
|
|
57
|
+
def fmap(&)
|
|
58
|
+
require_block(&)
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
# Evaluate applicative block
|
|
62
62
|
#
|
|
63
63
|
# @return [Either::Left<Object>]
|
|
64
|
-
def bind(&
|
|
65
|
-
require_block(&
|
|
64
|
+
def bind(&)
|
|
65
|
+
require_block(&)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
# Unwrap value from left
|
|
@@ -137,8 +137,8 @@ module Unparser
|
|
|
137
137
|
# Map over left value
|
|
138
138
|
#
|
|
139
139
|
# @return [Either::Right<Object>]
|
|
140
|
-
def lmap(&
|
|
141
|
-
require_block(&
|
|
140
|
+
def lmap(&)
|
|
141
|
+
require_block(&)
|
|
142
142
|
end
|
|
143
143
|
|
|
144
144
|
# Evaluate right side of branch
|
|
@@ -13,7 +13,11 @@ module Unparser
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def emit_def_arguments
|
|
16
|
-
|
|
16
|
+
if children.one? && n_mlhs?(Util.one(children))
|
|
17
|
+
emitter(Util.one(children)).dispatch_def
|
|
18
|
+
else
|
|
19
|
+
delimited(normal_arguments)
|
|
20
|
+
end
|
|
17
21
|
end
|
|
18
22
|
|
|
19
23
|
def emit_lambda_arguments
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
module Unparser
|
|
4
4
|
class Emitter
|
|
5
|
-
# Emitter for
|
|
6
|
-
class
|
|
5
|
+
# Emitter for forwarding arguments
|
|
6
|
+
class ForwardArg < self
|
|
7
7
|
MAP = {
|
|
8
|
-
blockarg:
|
|
9
|
-
|
|
8
|
+
blockarg: '&',
|
|
9
|
+
forwarded_kwrestarg: '**',
|
|
10
|
+
forwarded_restarg: '*',
|
|
11
|
+
kwrestarg: '**'
|
|
10
12
|
}.freeze
|
|
11
13
|
|
|
12
14
|
handle(*MAP.keys)
|
|
@@ -12,18 +12,10 @@ module Unparser
|
|
|
12
12
|
|
|
13
13
|
def dispatch
|
|
14
14
|
write('[')
|
|
15
|
-
delimited(children
|
|
15
|
+
delimited(children)
|
|
16
16
|
write(', ') if node_type.equal?(:array_pattern_with_tail)
|
|
17
17
|
write(']')
|
|
18
18
|
end
|
|
19
|
-
|
|
20
|
-
def emit_member(node)
|
|
21
|
-
if n_match_rest?(node)
|
|
22
|
-
writer_with(MatchRest, node).emit_array_pattern
|
|
23
|
-
else
|
|
24
|
-
visit(node)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
19
|
end # Pin
|
|
28
20
|
end # Emitter
|
|
29
21
|
end # Unparser
|
|
@@ -11,12 +11,6 @@ module Unparser
|
|
|
11
11
|
true
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def emit_heredoc_reminders
|
|
15
|
-
return unless right
|
|
16
|
-
|
|
17
|
-
emitter(right).emit_heredoc_reminders
|
|
18
|
-
end
|
|
19
|
-
|
|
20
14
|
private
|
|
21
15
|
|
|
22
16
|
def dispatch
|
|
@@ -30,12 +24,27 @@ module Unparser
|
|
|
30
24
|
write(' = ')
|
|
31
25
|
|
|
32
26
|
if BINARY_OPERATOR.include?(right.type)
|
|
33
|
-
writer_with(Writer::Binary, right).emit_operator
|
|
27
|
+
writer_with(Writer::Binary, node: right).emit_operator
|
|
28
|
+
elsif n_array?(right)
|
|
29
|
+
emit_array
|
|
30
|
+
else
|
|
31
|
+
right_emitter.write_to_buffer
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def emit_array
|
|
36
|
+
if right.children.size > 1
|
|
37
|
+
delimited(right.children)
|
|
34
38
|
else
|
|
35
|
-
|
|
39
|
+
right_emitter.write_to_buffer
|
|
36
40
|
end
|
|
37
41
|
end
|
|
38
42
|
|
|
43
|
+
def right_emitter
|
|
44
|
+
emitter(right)
|
|
45
|
+
end
|
|
46
|
+
memoize :right_emitter
|
|
47
|
+
|
|
39
48
|
abstract_method :emit_left
|
|
40
49
|
|
|
41
50
|
# Variable assignment emitter
|