unparser 0.6.7 → 0.9.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 +10 -10
- data/lib/unparser/adamantium.rb +3 -1
- data/lib/unparser/anima.rb +12 -3
- data/lib/unparser/ast/local_variable_scope.rb +29 -26
- data/lib/unparser/ast.rb +32 -49
- data/lib/unparser/buffer.rb +44 -2
- data/lib/unparser/cli.rb +48 -11
- data/lib/unparser/color.rb +9 -1
- data/lib/unparser/comments.rb +2 -2
- data/lib/unparser/diff.rb +8 -1
- data/lib/unparser/either.rb +13 -11
- data/lib/unparser/emitter/args.rb +5 -1
- 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 +18 -7
- 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 -8
- 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 +4 -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 +11 -11
- data/lib/unparser/equalizer.rb +105 -71
- data/lib/unparser/generation.rb +33 -29
- data/lib/unparser/node_details/send.rb +1 -0
- data/lib/unparser/node_details.rb +8 -1
- data/lib/unparser/node_helpers.rb +19 -9
- data/lib/unparser/util.rb +24 -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 +130 -138
- 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 +157 -41
- metadata +82 -33
- data/lib/unparser/concord.rb +0 -114
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 55ff925fe35a0edc1d97f78f4c2cf18590a3f2b4a11bc33e4b786a5954b4a38b
|
|
4
|
+
data.tar.gz: 41298c66c043f4f886215b23f6e1b16cd5bfc4fda9cac590a4dcfbf79c7b3ad8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '08b368b24f292f467d75f2cbbea4488dc117fbfc1619c0ab14eee351121221bf63d0c60aa8cffb1cc9f795eb87fd0a5e0d1cefd196ec955f8d3c0b12784f57a6'
|
|
7
|
+
data.tar.gz: 9a21fffcd287e446c6e5a459556d1c863490ebbaa906ea4f775619286405d18fab3821c5fc3e14ba4ab8fc8f68de344b6a71565f7e8980f8eac43a762b7caf66
|
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 >=
|
|
13
|
+
* Only support for Ruby >= 3.3
|
|
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
|
------------
|
|
@@ -173,12 +173,12 @@ Included Libraries
|
|
|
173
173
|
|
|
174
174
|
For dependency reduction reasons unparser ships vendored (and reduced) versions of:
|
|
175
175
|
|
|
176
|
-
* [abstract_type](https://github.com/
|
|
176
|
+
* [abstract_type](https://github.com/dkubb/abstract_type) -> Unparser::AbstractType
|
|
177
177
|
* [adamantium](https://github.com/dkubb/adamantium) -> Unparser::Adamantium
|
|
178
|
-
* [anima](https://github.com/mbj/
|
|
179
|
-
* [
|
|
180
|
-
* [memoizable](https://github.com/dkubb/memoizable) -> Unparser::
|
|
181
|
-
* [mprelude](
|
|
178
|
+
* [anima](https://github.com/mbj/anima) -> Unparser::Anima
|
|
179
|
+
* [equalizer](https://github.com/dkubb/equalizer) -> Unparser::Equalizer
|
|
180
|
+
* [memoizable](https://github.com/dkubb/memoizable) -> Unparser::Memoizable
|
|
181
|
+
* [mprelude](http://prelude.rubyforge.org/) -> Unparser::Either
|
|
182
182
|
|
|
183
183
|
Contributing
|
|
184
184
|
-------------
|
data/lib/unparser/adamantium.rb
CHANGED
data/lib/unparser/anima.rb
CHANGED
|
@@ -50,9 +50,7 @@ module Unparser
|
|
|
50
50
|
#
|
|
51
51
|
# @return [Hash]
|
|
52
52
|
def attributes_hash(object)
|
|
53
|
-
attributes.
|
|
54
|
-
attributes_hash[attribute.name] = attribute.get(object)
|
|
55
|
-
end
|
|
53
|
+
attributes.to_h { |attribute| [attribute.name, attribute.get(object)] }
|
|
56
54
|
end
|
|
57
55
|
|
|
58
56
|
# Return attribute names
|
|
@@ -134,14 +132,25 @@ module Unparser
|
|
|
134
132
|
# @param [Class, Module] scope
|
|
135
133
|
#
|
|
136
134
|
# @return [undefined]
|
|
135
|
+
#
|
|
136
|
+
# mutant:disable
|
|
137
137
|
def included(descendant)
|
|
138
138
|
descendant.instance_exec(self, attribute_names) do |anima, names|
|
|
139
139
|
# Define anima method
|
|
140
|
+
|
|
141
|
+
class << self
|
|
142
|
+
undef_method(:anima) if method_defined?(:anima)
|
|
143
|
+
end
|
|
144
|
+
|
|
140
145
|
define_singleton_method(:anima) { anima }
|
|
141
146
|
|
|
142
147
|
# Define instance methods
|
|
143
148
|
include InstanceMethods
|
|
144
149
|
|
|
150
|
+
names.each do |name|
|
|
151
|
+
undef_method(name) if method_defined?(name)
|
|
152
|
+
end
|
|
153
|
+
|
|
145
154
|
# Define attribute readers
|
|
146
155
|
attr_reader(*names)
|
|
147
156
|
|
|
@@ -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:, &)
|
|
111
|
+
new(stack: stack).each(node: node, &)
|
|
109
112
|
end
|
|
110
113
|
|
|
111
114
|
# Enumerate local variable scope scope
|
|
@@ -118,8 +121,8 @@ module Unparser
|
|
|
118
121
|
#
|
|
119
122
|
# @api private
|
|
120
123
|
#
|
|
121
|
-
def each(node
|
|
122
|
-
visit(node, &
|
|
124
|
+
def each(node:, &)
|
|
125
|
+
visit(node, &)
|
|
123
126
|
end
|
|
124
127
|
|
|
125
128
|
private
|
|
@@ -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,
|
|
@@ -78,19 +90,13 @@ module Unparser
|
|
|
78
90
|
|
|
79
91
|
# AST enumerator
|
|
80
92
|
class Enumerator
|
|
81
|
-
include Adamantium,
|
|
93
|
+
include Adamantium, Equalizer.new(:node, :controller), Enumerable
|
|
82
94
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
# @return [Enumerator]
|
|
89
|
-
#
|
|
90
|
-
# @api private
|
|
91
|
-
#
|
|
92
|
-
def self.new(node, controller = TAUTOLOGY)
|
|
93
|
-
super
|
|
95
|
+
attr_reader :node, :controller
|
|
96
|
+
|
|
97
|
+
def initialize(node, controller)
|
|
98
|
+
@node = node
|
|
99
|
+
@controller = controller
|
|
94
100
|
end
|
|
95
101
|
|
|
96
102
|
# Return each node
|
|
@@ -103,8 +109,8 @@ module Unparser
|
|
|
103
109
|
#
|
|
104
110
|
# @api private
|
|
105
111
|
#
|
|
106
|
-
def each(&
|
|
107
|
-
Walker.call(node, controller, &
|
|
112
|
+
def each(&)
|
|
113
|
+
Walker.call(node, controller, &)
|
|
108
114
|
end
|
|
109
115
|
|
|
110
116
|
# Return nodes selected by types
|
|
@@ -131,50 +137,27 @@ module Unparser
|
|
|
131
137
|
select { |node| node.type.equal?(type) }
|
|
132
138
|
end
|
|
133
139
|
|
|
134
|
-
# Return frozne set of objects
|
|
135
|
-
#
|
|
136
|
-
# @param [Enumerable] enumerable
|
|
137
|
-
#
|
|
138
|
-
# @return [Set]
|
|
139
|
-
#
|
|
140
|
-
# @api private
|
|
141
|
-
#
|
|
142
|
-
def self.set(enumerable)
|
|
143
|
-
enumerable.to_set.freeze
|
|
144
|
-
end
|
|
145
|
-
private_class_method :set
|
|
146
|
-
|
|
147
|
-
# Return nodes of type
|
|
148
|
-
#
|
|
149
|
-
# @param [Parser::AST::Node] node
|
|
150
|
-
# @param [Symbol] type
|
|
151
|
-
#
|
|
152
|
-
# @return [Enumerable<Parser::AST::Node]
|
|
153
|
-
#
|
|
154
|
-
# @api private
|
|
155
|
-
#
|
|
156
|
-
def self.type(node, type)
|
|
157
|
-
new(node).type(type)
|
|
158
|
-
end
|
|
159
|
-
private_class_method :type
|
|
160
|
-
|
|
161
140
|
end # Enumerator
|
|
162
141
|
|
|
163
142
|
# Controlled AST walker walking the AST in deeth first search with pre order
|
|
164
143
|
class Walker
|
|
165
|
-
include
|
|
144
|
+
include Equalizer.new(:block, :controller)
|
|
145
|
+
|
|
146
|
+
attr_reader :block, :controller
|
|
147
|
+
|
|
148
|
+
def initialize(block, controller)
|
|
149
|
+
@block = block
|
|
150
|
+
@controller = controller
|
|
151
|
+
end
|
|
166
152
|
|
|
167
153
|
# Call ast walker
|
|
168
154
|
#
|
|
169
155
|
# @param [Parser::AST::Node] node
|
|
170
156
|
#
|
|
171
|
-
# @return [self]
|
|
172
|
-
#
|
|
173
157
|
# @api private
|
|
174
158
|
#
|
|
175
|
-
def self.call(node, controller
|
|
159
|
+
def self.call(node, controller, &block)
|
|
176
160
|
new(block, controller).call(node)
|
|
177
|
-
self
|
|
178
161
|
end
|
|
179
162
|
|
|
180
163
|
# 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
|
|
@@ -68,6 +77,10 @@ module Unparser
|
|
|
68
77
|
self
|
|
69
78
|
end
|
|
70
79
|
|
|
80
|
+
def ensure_nl
|
|
81
|
+
nl unless fresh_line?
|
|
82
|
+
end
|
|
83
|
+
|
|
71
84
|
# Write newline
|
|
72
85
|
#
|
|
73
86
|
# @return [self]
|
|
@@ -75,7 +88,27 @@ module Unparser
|
|
|
75
88
|
# @api private
|
|
76
89
|
#
|
|
77
90
|
def nl
|
|
91
|
+
@no_nl = false
|
|
78
92
|
write(NL)
|
|
93
|
+
flush_heredocs
|
|
94
|
+
self
|
|
95
|
+
end
|
|
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
|
|
79
112
|
end
|
|
80
113
|
|
|
81
114
|
def root_indent
|
|
@@ -117,6 +150,10 @@ module Unparser
|
|
|
117
150
|
self
|
|
118
151
|
end
|
|
119
152
|
|
|
153
|
+
def write_encoding(encoding)
|
|
154
|
+
write("# -*- encoding: #{encoding} -*-\n")
|
|
155
|
+
end
|
|
156
|
+
|
|
120
157
|
private
|
|
121
158
|
|
|
122
159
|
INDENT_SPACE = ' '.freeze
|
|
@@ -125,5 +162,10 @@ module Unparser
|
|
|
125
162
|
write(INDENT_SPACE * @indent)
|
|
126
163
|
end
|
|
127
164
|
|
|
165
|
+
def flush_heredocs
|
|
166
|
+
@heredocs.each(&public_method(:write))
|
|
167
|
+
@heredocs = []
|
|
168
|
+
end
|
|
169
|
+
|
|
128
170
|
end # Buffer
|
|
129
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
|
|
@@ -12,7 +14,15 @@ module Unparser
|
|
|
12
14
|
|
|
13
15
|
# Path target
|
|
14
16
|
class Path < self
|
|
15
|
-
include
|
|
17
|
+
include Equalizer.new(:path)
|
|
18
|
+
|
|
19
|
+
attr_reader :path
|
|
20
|
+
|
|
21
|
+
# rubocop:disable Lint/MissingSuper
|
|
22
|
+
def initialize(path)
|
|
23
|
+
@path = path
|
|
24
|
+
end
|
|
25
|
+
# rubocop:enable Lint/MissingSuper
|
|
16
26
|
|
|
17
27
|
# Validation for this target
|
|
18
28
|
#
|
|
@@ -31,7 +41,13 @@ module Unparser
|
|
|
31
41
|
|
|
32
42
|
# String target
|
|
33
43
|
class String
|
|
34
|
-
include
|
|
44
|
+
include Equalizer.new(:string)
|
|
45
|
+
|
|
46
|
+
attr_reader :string
|
|
47
|
+
|
|
48
|
+
def initialize(string)
|
|
49
|
+
@string = string
|
|
50
|
+
end
|
|
35
51
|
|
|
36
52
|
# Validation for this target
|
|
37
53
|
#
|
|
@@ -60,8 +76,9 @@ module Unparser
|
|
|
60
76
|
#
|
|
61
77
|
# @api private
|
|
62
78
|
#
|
|
63
|
-
|
|
64
|
-
|
|
79
|
+
# mutant:disable
|
|
80
|
+
def self.run(*)
|
|
81
|
+
new(*).exit_status
|
|
65
82
|
end
|
|
66
83
|
|
|
67
84
|
# Initialize object
|
|
@@ -71,15 +88,17 @@ module Unparser
|
|
|
71
88
|
# @return [undefined]
|
|
72
89
|
#
|
|
73
90
|
# @api private
|
|
91
|
+
# mutant:disable
|
|
74
92
|
def initialize(arguments)
|
|
75
93
|
@ignore = Set.new
|
|
76
94
|
@targets = []
|
|
77
95
|
|
|
78
|
-
@fail_fast
|
|
79
|
-
@start_with
|
|
80
|
-
@success
|
|
81
|
-
@validation
|
|
82
|
-
@verbose
|
|
96
|
+
@fail_fast = false
|
|
97
|
+
@start_with = nil
|
|
98
|
+
@success = true
|
|
99
|
+
@validation = :validation
|
|
100
|
+
@verbose = false
|
|
101
|
+
@ignore_original_syntax_error = false
|
|
83
102
|
|
|
84
103
|
opts = OptionParser.new do |builder|
|
|
85
104
|
add_options(builder)
|
|
@@ -98,6 +117,7 @@ module Unparser
|
|
|
98
117
|
#
|
|
99
118
|
# @api private
|
|
100
119
|
#
|
|
120
|
+
# mutant:disable
|
|
101
121
|
# rubocop:disable Metrics/MethodLength
|
|
102
122
|
def add_options(builder)
|
|
103
123
|
builder.banner = 'usage: unparse [options] FILE [FILE]'
|
|
@@ -114,6 +134,9 @@ module Unparser
|
|
|
114
134
|
builder.on('-l', '--literal') do
|
|
115
135
|
@validation = :literal_validation
|
|
116
136
|
end
|
|
137
|
+
builder.on('--ignore-original-syntax-error') do
|
|
138
|
+
@ignore_original_syntax_error = true
|
|
139
|
+
end
|
|
117
140
|
builder.on('--ignore FILE') do |file|
|
|
118
141
|
@ignore.merge(targets(file))
|
|
119
142
|
end
|
|
@@ -129,6 +152,7 @@ module Unparser
|
|
|
129
152
|
#
|
|
130
153
|
# @api private
|
|
131
154
|
#
|
|
155
|
+
# mutant:disable
|
|
132
156
|
def exit_status
|
|
133
157
|
effective_targets.each do |target|
|
|
134
158
|
process_target(target)
|
|
@@ -140,11 +164,15 @@ module Unparser
|
|
|
140
164
|
|
|
141
165
|
private
|
|
142
166
|
|
|
167
|
+
# mutant:disable
|
|
143
168
|
def process_target(target)
|
|
144
169
|
validation = target.public_send(@validation)
|
|
145
170
|
if validation.success?
|
|
146
171
|
puts validation.report if @verbose
|
|
147
172
|
puts "Success: #{validation.identification}"
|
|
173
|
+
elsif ignore_original_syntax_error?(validation)
|
|
174
|
+
exception = validation.original_node.from_left
|
|
175
|
+
puts "#{exception.class}: #{validation.identification} #{exception}"
|
|
148
176
|
else
|
|
149
177
|
puts validation.report
|
|
150
178
|
puts "Error: #{validation.identification}"
|
|
@@ -152,6 +180,14 @@ module Unparser
|
|
|
152
180
|
end
|
|
153
181
|
end
|
|
154
182
|
|
|
183
|
+
# mutant:disable
|
|
184
|
+
def ignore_original_syntax_error?(validation)
|
|
185
|
+
@ignore_original_syntax_error && validation.original_node.from_left do
|
|
186
|
+
nil
|
|
187
|
+
end.instance_of?(Parser::SyntaxError)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# mutant:disable
|
|
155
191
|
def effective_targets
|
|
156
192
|
if @start_with
|
|
157
193
|
reject = true
|
|
@@ -167,13 +203,14 @@ module Unparser
|
|
|
167
203
|
end.reject(&@ignore.method(:include?))
|
|
168
204
|
end
|
|
169
205
|
|
|
206
|
+
# mutant:disable
|
|
170
207
|
def targets(file_name)
|
|
171
208
|
if File.directory?(file_name)
|
|
172
|
-
Dir.glob(File.join(file_name, '**/*.rb'))
|
|
209
|
+
Dir.glob(File.join(file_name, '**/*.rb'))
|
|
173
210
|
elsif File.file?(file_name)
|
|
174
211
|
[file_name]
|
|
175
212
|
else
|
|
176
|
-
Dir.glob(file_name)
|
|
213
|
+
Dir.glob(file_name)
|
|
177
214
|
end.map { |file| Target::Path.new(Pathname.new(file)) }
|
|
178
215
|
end
|
|
179
216
|
end # CLI
|
data/lib/unparser/color.rb
CHANGED
|
@@ -3,7 +3,13 @@
|
|
|
3
3
|
module Unparser
|
|
4
4
|
# Class to colorize strings
|
|
5
5
|
class Color
|
|
6
|
-
include Adamantium,
|
|
6
|
+
include Adamantium, Equalizer.new(:code)
|
|
7
|
+
|
|
8
|
+
attr_reader :code
|
|
9
|
+
|
|
10
|
+
def initialize(code)
|
|
11
|
+
@code = code
|
|
12
|
+
end
|
|
7
13
|
|
|
8
14
|
# Format text with color
|
|
9
15
|
#
|
|
@@ -30,8 +36,10 @@ module Unparser
|
|
|
30
36
|
|
|
31
37
|
# Well rubocop you are static so you do not have a clue here ;)
|
|
32
38
|
# rubocop:disable Style/RedundantInitialize
|
|
39
|
+
# rubocop:disable Lint/MissingSuper
|
|
33
40
|
def initialize; end
|
|
34
41
|
# rubocop:enable Style/RedundantInitialize
|
|
42
|
+
# rubocop:enable Lint/MissingSuper
|
|
35
43
|
|
|
36
44
|
end.new
|
|
37
45
|
|
data/lib/unparser/comments.rb
CHANGED
data/lib/unparser/diff.rb
CHANGED
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
module Unparser
|
|
4
4
|
# Class to create diffs from source code
|
|
5
5
|
class Diff
|
|
6
|
-
include Adamantium,
|
|
6
|
+
include Adamantium, Equalizer.new(:old, :new)
|
|
7
|
+
|
|
8
|
+
attr_reader :old, :new
|
|
9
|
+
|
|
10
|
+
def initialize(old, new)
|
|
11
|
+
@old = old
|
|
12
|
+
@new = new
|
|
13
|
+
end
|
|
7
14
|
|
|
8
15
|
ADDITION = '+'
|
|
9
16
|
DELETION = '-'
|