unparser 0.4.7 → 0.6.7
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 +40 -9
- data/bin/unparser +2 -2
- data/lib/unparser/abstract_type.rb +121 -0
- data/lib/unparser/adamantium/method_builder.rb +111 -0
- data/lib/unparser/adamantium.rb +150 -0
- data/lib/unparser/anima/attribute.rb +59 -0
- data/lib/unparser/anima/error.rb +23 -0
- data/lib/unparser/anima.rb +184 -0
- data/lib/unparser/ast/local_variable_scope.rb +6 -76
- data/lib/unparser/ast.rb +1 -3
- data/lib/unparser/buffer.rb +14 -25
- data/lib/unparser/cli.rb +85 -77
- data/lib/unparser/{cli/color.rb → color.rb} +4 -14
- data/lib/unparser/comments.rb +0 -26
- data/lib/unparser/concord.rb +114 -0
- data/lib/unparser/constants.rb +4 -53
- data/lib/unparser/diff.rb +98 -0
- data/lib/unparser/dsl.rb +0 -32
- data/lib/unparser/either.rb +153 -0
- data/lib/unparser/emitter/alias.rb +2 -8
- data/lib/unparser/emitter/args.rb +45 -0
- data/lib/unparser/emitter/argument.rb +13 -169
- data/lib/unparser/emitter/array.rb +27 -0
- data/lib/unparser/emitter/array_pattern.rb +29 -0
- data/lib/unparser/emitter/assignment.rb +36 -127
- data/lib/unparser/emitter/begin.rb +9 -84
- data/lib/unparser/emitter/binary.rb +7 -20
- data/lib/unparser/emitter/block.rb +57 -41
- data/lib/unparser/emitter/case.rb +6 -48
- data/lib/unparser/emitter/case_guard.rb +27 -0
- data/lib/unparser/emitter/case_match.rb +40 -0
- data/lib/unparser/emitter/cbase.rb +1 -3
- data/lib/unparser/emitter/class.rb +6 -26
- data/lib/unparser/emitter/const_pattern.rb +24 -0
- data/lib/unparser/emitter/def.rb +7 -51
- data/lib/unparser/emitter/defined.rb +2 -12
- data/lib/unparser/emitter/dstr.rb +22 -0
- data/lib/unparser/emitter/dsym.rb +41 -0
- data/lib/unparser/emitter/find_pattern.rb +18 -0
- data/lib/unparser/emitter/flipflop.rb +11 -10
- data/lib/unparser/emitter/float.rb +29 -0
- data/lib/unparser/emitter/flow_modifier.rb +15 -53
- data/lib/unparser/emitter/for.rb +5 -19
- data/lib/unparser/emitter/hash.rb +36 -0
- data/lib/unparser/emitter/hash_pattern.rb +67 -0
- data/lib/unparser/emitter/hookexe.rb +5 -11
- data/lib/unparser/emitter/if.rb +15 -71
- data/lib/unparser/emitter/in_match.rb +21 -0
- data/lib/unparser/emitter/in_pattern.rb +36 -0
- data/lib/unparser/emitter/index.rb +22 -89
- data/lib/unparser/emitter/kwargs.rb +13 -0
- data/lib/unparser/emitter/kwbegin.rb +31 -0
- data/lib/unparser/emitter/lambda.rb +0 -8
- data/lib/unparser/emitter/masgn.rb +20 -0
- data/lib/unparser/emitter/match.rb +3 -17
- data/lib/unparser/emitter/match_alt.rb +23 -0
- data/lib/unparser/emitter/match_as.rb +21 -0
- data/lib/unparser/emitter/match_pattern.rb +30 -0
- data/lib/unparser/emitter/match_pattern_p.rb +20 -0
- data/lib/unparser/emitter/match_rest.rb +33 -0
- data/lib/unparser/emitter/match_var.rb +19 -0
- data/lib/unparser/emitter/mlhs.rb +40 -0
- data/lib/unparser/emitter/module.rb +3 -9
- data/lib/unparser/emitter/op_assign.rb +14 -29
- data/lib/unparser/emitter/pair.rb +33 -0
- data/lib/unparser/emitter/pin.rb +19 -0
- data/lib/unparser/emitter/primitive.rb +93 -0
- data/lib/unparser/emitter/range.rb +35 -0
- data/lib/unparser/emitter/regexp.rb +35 -0
- data/lib/unparser/emitter/repetition.rb +17 -57
- data/lib/unparser/emitter/rescue.rb +1 -97
- data/lib/unparser/emitter/root.rb +17 -1
- data/lib/unparser/emitter/send.rb +10 -219
- data/lib/unparser/emitter/simple.rb +33 -0
- data/lib/unparser/emitter/splat.rb +13 -19
- data/lib/unparser/emitter/super.rb +1 -29
- data/lib/unparser/emitter/undef.rb +1 -9
- data/lib/unparser/emitter/variable.rb +1 -31
- data/lib/unparser/emitter/xstr.rb +72 -0
- data/lib/unparser/emitter/yield.rb +1 -9
- data/lib/unparser/emitter.rb +24 -425
- data/lib/unparser/equalizer.rb +98 -0
- data/lib/unparser/generation.rb +252 -0
- data/lib/unparser/node_details/send.rb +65 -0
- data/lib/unparser/node_details.rb +21 -0
- data/lib/unparser/node_helpers.rb +48 -6
- data/lib/unparser/validation.rb +172 -0
- data/lib/unparser/writer/binary.rb +99 -0
- data/lib/unparser/writer/dynamic_string.rb +211 -0
- data/lib/unparser/writer/resbody.rb +40 -0
- data/lib/unparser/writer/rescue.rb +43 -0
- data/lib/unparser/{emitter → writer}/send/attribute_assignment.rb +11 -26
- data/lib/unparser/writer/send/binary.rb +27 -0
- data/lib/unparser/writer/send/conditional.rb +25 -0
- data/lib/unparser/writer/send/regular.rb +33 -0
- data/lib/unparser/{emitter → writer}/send/unary.rb +10 -17
- data/lib/unparser/writer/send.rb +115 -0
- data/lib/unparser/writer.rb +15 -0
- data/lib/unparser.rb +161 -77
- metadata +100 -157
- data/.circleci/config.yml +0 -49
- data/.gitignore +0 -37
- data/.rspec +0 -4
- data/.rubocop.yml +0 -9
- data/Changelog.md +0 -156
- data/Gemfile +0 -9
- data/Gemfile.lock +0 -181
- data/LICENSE +0 -20
- data/Rakefile +0 -22
- data/config/devtools.yml +0 -2
- data/config/flay.yml +0 -3
- data/config/flog.yml +0 -2
- data/config/mutant.yml +0 -6
- data/config/reek.yml +0 -98
- data/config/rubocop.yml +0 -122
- data/config/yardstick.yml +0 -2
- data/lib/unparser/cli/differ.rb +0 -152
- data/lib/unparser/cli/source.rb +0 -267
- data/lib/unparser/emitter/empty.rb +0 -23
- data/lib/unparser/emitter/ensure.rb +0 -37
- data/lib/unparser/emitter/literal/array.rb +0 -29
- data/lib/unparser/emitter/literal/dynamic.rb +0 -53
- data/lib/unparser/emitter/literal/dynamic_body.rb +0 -132
- data/lib/unparser/emitter/literal/execute_string.rb +0 -38
- data/lib/unparser/emitter/literal/hash.rb +0 -156
- data/lib/unparser/emitter/literal/primitive.rb +0 -145
- data/lib/unparser/emitter/literal/range.rb +0 -36
- data/lib/unparser/emitter/literal/regexp.rb +0 -114
- data/lib/unparser/emitter/literal/singleton.rb +0 -26
- data/lib/unparser/emitter/literal.rb +0 -10
- data/lib/unparser/emitter/meta.rb +0 -16
- data/lib/unparser/emitter/redo.rb +0 -25
- data/lib/unparser/emitter/resbody.rb +0 -76
- data/lib/unparser/emitter/retry.rb +0 -25
- data/lib/unparser/emitter/send/binary.rb +0 -57
- data/lib/unparser/emitter/send/conditional.rb +0 -40
- data/lib/unparser/emitter/send/regular.rb +0 -40
- data/lib/unparser/preprocessor.rb +0 -159
- data/spec/integration/unparser/corpus_spec.rb +0 -111
- data/spec/integrations.yml +0 -92
- data/spec/spec_helper.rb +0 -20
- data/spec/unit/unparser/buffer/append_spec.rb +0 -24
- data/spec/unit/unparser/buffer/append_without_prefix_spec.rb +0 -23
- data/spec/unit/unparser/buffer/capture_content_spec.rb +0 -17
- data/spec/unit/unparser/buffer/content_spec.rb +0 -38
- data/spec/unit/unparser/buffer/fresh_line_spec.rb +0 -20
- data/spec/unit/unparser/buffer/indent_spec.rb +0 -20
- data/spec/unit/unparser/buffer/nl_spec.rb +0 -16
- data/spec/unit/unparser/buffer/unindent_spec.rb +0 -20
- data/spec/unit/unparser/comments/consume_spec.rb +0 -22
- data/spec/unit/unparser/comments/take_all_spec.rb +0 -19
- data/spec/unit/unparser/comments/take_before_spec.rb +0 -46
- data/spec/unit/unparser/comments/take_eol_comments_spec.rb +0 -32
- data/spec/unit/unparser/emitter/class_methods/handle_spec.rb +0 -17
- data/spec/unit/unparser_spec.rb +0 -1849
- data/unparser.gemspec +0 -32
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
# Original code before vendoring and reduction from: https://github.com/mbj/anima.
|
|
5
|
+
class Anima < Module
|
|
6
|
+
include Adamantium, Equalizer.new(:attributes)
|
|
7
|
+
|
|
8
|
+
# Return names
|
|
9
|
+
#
|
|
10
|
+
# @return [AttributeSet]
|
|
11
|
+
attr_reader :attributes
|
|
12
|
+
|
|
13
|
+
# Initialize object
|
|
14
|
+
#
|
|
15
|
+
# @return [undefined]
|
|
16
|
+
#
|
|
17
|
+
# rubocop:disable Lint/MissingSuper
|
|
18
|
+
def initialize(*names)
|
|
19
|
+
@attributes = names.uniq.map(&Attribute.public_method(:new)).freeze
|
|
20
|
+
end
|
|
21
|
+
# rubocop:enable Lint/MissingSuper
|
|
22
|
+
|
|
23
|
+
# Return new anima with attributes added
|
|
24
|
+
#
|
|
25
|
+
# @return [Anima]
|
|
26
|
+
#
|
|
27
|
+
# @example
|
|
28
|
+
# anima = Anima.new(:foo)
|
|
29
|
+
# anima.add(:bar) # equals Anima.new(:foo, :bar)
|
|
30
|
+
#
|
|
31
|
+
def add(*names)
|
|
32
|
+
new(attribute_names + names)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Return new anima with attributes removed
|
|
36
|
+
#
|
|
37
|
+
# @return [Anima]
|
|
38
|
+
#
|
|
39
|
+
# @example
|
|
40
|
+
# anima = Anima.new(:foo, :bar)
|
|
41
|
+
# anima.remove(:bar) # equals Anima.new(:foo)
|
|
42
|
+
#
|
|
43
|
+
def remove(*names)
|
|
44
|
+
new(attribute_names - names)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Return attributes hash for instance
|
|
48
|
+
#
|
|
49
|
+
# @param [Object] object
|
|
50
|
+
#
|
|
51
|
+
# @return [Hash]
|
|
52
|
+
def attributes_hash(object)
|
|
53
|
+
attributes.each_with_object({}) do |attribute, attributes_hash|
|
|
54
|
+
attributes_hash[attribute.name] = attribute.get(object)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Return attribute names
|
|
59
|
+
#
|
|
60
|
+
# @return [Enumerable<Symbol>]
|
|
61
|
+
def attribute_names
|
|
62
|
+
attributes.map(&:name)
|
|
63
|
+
end
|
|
64
|
+
memoize :attribute_names
|
|
65
|
+
|
|
66
|
+
# Initialize instance
|
|
67
|
+
#
|
|
68
|
+
# @param [Object] object
|
|
69
|
+
#
|
|
70
|
+
# @param [Hash] attribute_hash
|
|
71
|
+
#
|
|
72
|
+
# @return [self]
|
|
73
|
+
def initialize_instance(object, attribute_hash)
|
|
74
|
+
assert_known_attributes(object.class, attribute_hash)
|
|
75
|
+
attributes.each do |attribute|
|
|
76
|
+
attribute.load(object, attribute_hash)
|
|
77
|
+
end
|
|
78
|
+
self
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Static instance methods for anima infected classes
|
|
82
|
+
module InstanceMethods
|
|
83
|
+
# Initialize an anima infected object
|
|
84
|
+
#
|
|
85
|
+
# @param [#to_h] attributes
|
|
86
|
+
# a hash that matches anima defined attributes
|
|
87
|
+
#
|
|
88
|
+
# @return [undefined]
|
|
89
|
+
#
|
|
90
|
+
# rubocop:disable Lint/MissingSuper
|
|
91
|
+
def initialize(attributes)
|
|
92
|
+
self.class.anima.initialize_instance(self, attributes)
|
|
93
|
+
end
|
|
94
|
+
# rubocop:enable Lint/MissingSuper
|
|
95
|
+
|
|
96
|
+
# Return a hash representation of an anima infected object
|
|
97
|
+
#
|
|
98
|
+
# @example
|
|
99
|
+
# anima.to_h # => { :foo => : bar }
|
|
100
|
+
#
|
|
101
|
+
# @return [Hash]
|
|
102
|
+
#
|
|
103
|
+
# @api public
|
|
104
|
+
def to_h
|
|
105
|
+
self.class.anima.attributes_hash(self)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Return updated instance
|
|
109
|
+
#
|
|
110
|
+
# @example
|
|
111
|
+
# klass = Class.new do
|
|
112
|
+
# include Anima.new(:foo, :bar)
|
|
113
|
+
# end
|
|
114
|
+
#
|
|
115
|
+
# foo = klass.new(:foo => 1, :bar => 2)
|
|
116
|
+
# updated = foo.with(:foo => 3)
|
|
117
|
+
# updated.foo # => 3
|
|
118
|
+
# updated.bar # => 2
|
|
119
|
+
#
|
|
120
|
+
# @param [Hash] attributes
|
|
121
|
+
#
|
|
122
|
+
# @return [Anima]
|
|
123
|
+
#
|
|
124
|
+
# @api public
|
|
125
|
+
def with(attributes)
|
|
126
|
+
self.class.new(to_h.update(attributes))
|
|
127
|
+
end
|
|
128
|
+
end # InstanceMethods
|
|
129
|
+
|
|
130
|
+
private
|
|
131
|
+
|
|
132
|
+
# Infect the instance with anima
|
|
133
|
+
#
|
|
134
|
+
# @param [Class, Module] scope
|
|
135
|
+
#
|
|
136
|
+
# @return [undefined]
|
|
137
|
+
def included(descendant)
|
|
138
|
+
descendant.instance_exec(self, attribute_names) do |anima, names|
|
|
139
|
+
# Define anima method
|
|
140
|
+
define_singleton_method(:anima) { anima }
|
|
141
|
+
|
|
142
|
+
# Define instance methods
|
|
143
|
+
include InstanceMethods
|
|
144
|
+
|
|
145
|
+
# Define attribute readers
|
|
146
|
+
attr_reader(*names)
|
|
147
|
+
|
|
148
|
+
# Define equalizer
|
|
149
|
+
include Equalizer.new(*names)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Fail unless keys in +attribute_hash+ matches #attribute_names
|
|
154
|
+
#
|
|
155
|
+
# @param [Class] klass
|
|
156
|
+
# the class being initialized
|
|
157
|
+
#
|
|
158
|
+
# @param [Hash] attribute_hash
|
|
159
|
+
# the attributes to initialize +object+ with
|
|
160
|
+
#
|
|
161
|
+
# @return [undefined]
|
|
162
|
+
#
|
|
163
|
+
# @raise [Error]
|
|
164
|
+
def assert_known_attributes(klass, attribute_hash)
|
|
165
|
+
keys = attribute_hash.keys
|
|
166
|
+
|
|
167
|
+
unknown = keys - attribute_names
|
|
168
|
+
missing = attribute_names - keys
|
|
169
|
+
|
|
170
|
+
unless unknown.empty? && missing.empty?
|
|
171
|
+
fail Error.new(klass, missing, unknown)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Return new instance
|
|
176
|
+
#
|
|
177
|
+
# @param [Enumerable<Symbol>] attributes
|
|
178
|
+
#
|
|
179
|
+
# @return [Anima]
|
|
180
|
+
def new(attributes)
|
|
181
|
+
self.class.new(*attributes)
|
|
182
|
+
end
|
|
183
|
+
end # Anima
|
|
184
|
+
end # Unparser
|
|
@@ -61,35 +61,22 @@ module Unparser
|
|
|
61
61
|
#
|
|
62
62
|
# @api private
|
|
63
63
|
#
|
|
64
|
-
def
|
|
65
|
-
condition_reads = AST.local_variable_reads(
|
|
64
|
+
def first_assignment_in?(left, right)
|
|
65
|
+
condition_reads = AST.local_variable_reads(right)
|
|
66
66
|
|
|
67
|
-
candidates = AST.local_variable_assignments(
|
|
68
|
-
|
|
69
|
-
condition_reads.include?(name)
|
|
67
|
+
candidates = AST.local_variable_assignments(left).select do |node|
|
|
68
|
+
condition_reads.include?(node.children.first)
|
|
70
69
|
end
|
|
71
70
|
|
|
72
|
-
candidates.any?
|
|
73
|
-
first_assignment?(node)
|
|
74
|
-
end
|
|
71
|
+
candidates.any?(&public_method(:first_assignment?))
|
|
75
72
|
end
|
|
76
73
|
|
|
77
74
|
private
|
|
78
75
|
|
|
79
|
-
# Match node
|
|
80
|
-
#
|
|
81
|
-
# @param [Parser::AST::Node] needle
|
|
82
|
-
# if block given
|
|
83
|
-
#
|
|
84
|
-
# @return [Boolean]
|
|
85
|
-
#
|
|
86
|
-
# @api private
|
|
87
|
-
#
|
|
88
76
|
def match(needle)
|
|
89
77
|
@items.each do |node, current, before|
|
|
90
78
|
return yield(current, before) if node.equal?(needle)
|
|
91
79
|
end
|
|
92
|
-
false
|
|
93
80
|
end
|
|
94
81
|
|
|
95
82
|
end # LocalVariableScope
|
|
@@ -137,25 +124,10 @@ module Unparser
|
|
|
137
124
|
|
|
138
125
|
private
|
|
139
126
|
|
|
140
|
-
# Return current set of local variables
|
|
141
|
-
#
|
|
142
|
-
# @return [Set<Symbol>]
|
|
143
|
-
#
|
|
144
|
-
# @api private
|
|
145
|
-
#
|
|
146
127
|
def current
|
|
147
128
|
@stack.last
|
|
148
129
|
end
|
|
149
130
|
|
|
150
|
-
# Visit node and record local variable state
|
|
151
|
-
#
|
|
152
|
-
# @param [Parser::AST::Node] node
|
|
153
|
-
#
|
|
154
|
-
# @return [undefined]
|
|
155
|
-
#
|
|
156
|
-
# @api private
|
|
157
|
-
#
|
|
158
|
-
# ignore :reek:LongYieldList
|
|
159
131
|
def visit(node, &block)
|
|
160
132
|
before = current.dup
|
|
161
133
|
enter(node)
|
|
@@ -166,75 +138,33 @@ module Unparser
|
|
|
166
138
|
leave(node)
|
|
167
139
|
end
|
|
168
140
|
|
|
169
|
-
# Record local variable state
|
|
170
|
-
#
|
|
171
|
-
# @param [Parser::AST::Node] node
|
|
172
|
-
#
|
|
173
|
-
# @return [undefined]
|
|
174
|
-
#
|
|
175
|
-
# @api private
|
|
176
|
-
#
|
|
177
141
|
def enter(node)
|
|
178
142
|
case node.type
|
|
179
143
|
when *RESET_NODES
|
|
180
144
|
push_reset
|
|
181
|
-
when
|
|
145
|
+
when ASSIGN_NODES
|
|
182
146
|
define(node.children.first)
|
|
183
147
|
when *INHERIT_NODES
|
|
184
148
|
push_inherit
|
|
185
149
|
end
|
|
186
150
|
end
|
|
187
151
|
|
|
188
|
-
# Pop from local variable state
|
|
189
|
-
#
|
|
190
|
-
# @param [Parser::AST::Node] node
|
|
191
|
-
#
|
|
192
|
-
# @return [undefined]
|
|
193
|
-
#
|
|
194
|
-
# @api private
|
|
195
|
-
#
|
|
196
152
|
def leave(node)
|
|
197
153
|
pop if CLOSE_NODES.include?(node.type)
|
|
198
154
|
end
|
|
199
155
|
|
|
200
|
-
# Define a local variable on current stack
|
|
201
|
-
#
|
|
202
|
-
# @param [Symbol] name
|
|
203
|
-
#
|
|
204
|
-
# @return [undefined]
|
|
205
|
-
#
|
|
206
|
-
# @api private
|
|
207
|
-
#
|
|
208
156
|
def define(name)
|
|
209
157
|
current << name
|
|
210
158
|
end
|
|
211
159
|
|
|
212
|
-
# Push reset scope on stack
|
|
213
|
-
#
|
|
214
|
-
# @return [undefined]
|
|
215
|
-
#
|
|
216
|
-
# @api private
|
|
217
|
-
#
|
|
218
160
|
def push_reset
|
|
219
161
|
@stack << Set.new
|
|
220
162
|
end
|
|
221
163
|
|
|
222
|
-
# Push inherited lvar scope on stack
|
|
223
|
-
#
|
|
224
|
-
# @return [undefined]
|
|
225
|
-
#
|
|
226
|
-
# @api private
|
|
227
|
-
#
|
|
228
164
|
def push_inherit
|
|
229
165
|
@stack << current.dup
|
|
230
166
|
end
|
|
231
167
|
|
|
232
|
-
# Pop lvar scope from stack
|
|
233
|
-
#
|
|
234
|
-
# @return [undefined]
|
|
235
|
-
#
|
|
236
|
-
# @api private
|
|
237
|
-
#
|
|
238
168
|
def pop
|
|
239
169
|
@stack.pop
|
|
240
170
|
end
|
data/lib/unparser/ast.rb
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Unparser
|
|
4
4
|
# Namespace for AST processing tools
|
|
5
|
-
# :reek:TooManyConstants
|
|
6
5
|
module AST
|
|
7
|
-
|
|
8
6
|
FIRST_CHILD = ->(node) { node.children.first }.freeze
|
|
9
7
|
TAUTOLOGY = ->(_node) { true }.freeze
|
|
10
8
|
|
|
@@ -80,7 +78,7 @@ module Unparser
|
|
|
80
78
|
|
|
81
79
|
# AST enumerator
|
|
82
80
|
class Enumerator
|
|
83
|
-
include Adamantium
|
|
81
|
+
include Adamantium, Concord.new(:node, :controller), Enumerable
|
|
84
82
|
|
|
85
83
|
# Return new instance
|
|
86
84
|
#
|
data/lib/unparser/buffer.rb
CHANGED
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
module Unparser
|
|
4
4
|
|
|
5
5
|
# Buffer used to emit into
|
|
6
|
-
#
|
|
7
|
-
# ignore :reek:TooManyMethods
|
|
8
6
|
class Buffer
|
|
9
7
|
|
|
10
8
|
NL = "\n".freeze
|
|
@@ -46,7 +44,6 @@ module Unparser
|
|
|
46
44
|
#
|
|
47
45
|
def append_without_prefix(string)
|
|
48
46
|
write(string)
|
|
49
|
-
self
|
|
50
47
|
end
|
|
51
48
|
|
|
52
49
|
# Increase indent
|
|
@@ -79,7 +76,13 @@ module Unparser
|
|
|
79
76
|
#
|
|
80
77
|
def nl
|
|
81
78
|
write(NL)
|
|
82
|
-
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def root_indent
|
|
82
|
+
before = @indent
|
|
83
|
+
@indent = 0
|
|
84
|
+
yield
|
|
85
|
+
@indent = before
|
|
83
86
|
end
|
|
84
87
|
|
|
85
88
|
# Test for a fresh line
|
|
@@ -102,39 +105,25 @@ module Unparser
|
|
|
102
105
|
@content.dup.freeze
|
|
103
106
|
end
|
|
104
107
|
|
|
105
|
-
#
|
|
108
|
+
# Write raw fragment to buffer
|
|
106
109
|
#
|
|
107
|
-
#
|
|
110
|
+
# Does not do indentation logic.
|
|
108
111
|
#
|
|
109
|
-
# @
|
|
112
|
+
# @param [String] fragment
|
|
110
113
|
#
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
# @return [self]
|
|
115
|
+
def write(fragment)
|
|
116
|
+
@content << fragment
|
|
117
|
+
self
|
|
115
118
|
end
|
|
116
119
|
|
|
117
120
|
private
|
|
118
121
|
|
|
119
122
|
INDENT_SPACE = ' '.freeze
|
|
120
123
|
|
|
121
|
-
# Write prefix
|
|
122
|
-
#
|
|
123
|
-
# @return [String]
|
|
124
|
-
#
|
|
125
|
-
# @api private
|
|
126
|
-
#
|
|
127
124
|
def prefix
|
|
128
125
|
write(INDENT_SPACE * @indent)
|
|
129
126
|
end
|
|
130
127
|
|
|
131
|
-
# Write to content buffer
|
|
132
|
-
#
|
|
133
|
-
# @param [String] fragment
|
|
134
|
-
#
|
|
135
|
-
def write(fragment)
|
|
136
|
-
@content << fragment
|
|
137
|
-
end
|
|
138
|
-
|
|
139
128
|
end # Buffer
|
|
140
129
|
end # Unparser
|
data/lib/unparser/cli.rb
CHANGED
|
@@ -1,29 +1,61 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'unparser'
|
|
4
|
-
require 'optparse'
|
|
5
|
-
require 'diff/lcs'
|
|
6
|
-
require 'diff/lcs/hunk'
|
|
7
|
-
|
|
8
|
-
require 'unparser/cli/source'
|
|
9
|
-
require 'unparser/cli/differ'
|
|
10
|
-
require 'unparser/cli/color'
|
|
11
|
-
|
|
12
3
|
module Unparser
|
|
13
4
|
# Unparser CLI implementation
|
|
14
|
-
#
|
|
15
|
-
# :reek:InstanceVariableAssumption
|
|
16
|
-
# :reek:TooManyInstanceVariables
|
|
17
5
|
class CLI
|
|
18
6
|
|
|
19
7
|
EXIT_SUCCESS = 0
|
|
20
8
|
EXIT_FAILURE = 1
|
|
21
9
|
|
|
10
|
+
class Target
|
|
11
|
+
include AbstractType
|
|
12
|
+
|
|
13
|
+
# Path target
|
|
14
|
+
class Path < self
|
|
15
|
+
include Concord.new(:path)
|
|
16
|
+
|
|
17
|
+
# Validation for this target
|
|
18
|
+
#
|
|
19
|
+
# @return [Validation]
|
|
20
|
+
def validation
|
|
21
|
+
Validation.from_path(path)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Literal for this target
|
|
25
|
+
#
|
|
26
|
+
# @return [Validation]
|
|
27
|
+
def literal_validation
|
|
28
|
+
Validation::Literal.from_path(path)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# String target
|
|
33
|
+
class String
|
|
34
|
+
include Concord.new(:string)
|
|
35
|
+
|
|
36
|
+
# Validation for this target
|
|
37
|
+
#
|
|
38
|
+
# @return [Validation]
|
|
39
|
+
def validation
|
|
40
|
+
Validation.from_string(string)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Literal for this target
|
|
44
|
+
#
|
|
45
|
+
# @return [Validation]
|
|
46
|
+
def literal_validation
|
|
47
|
+
Validation::Literal.from_string(path)
|
|
48
|
+
end
|
|
49
|
+
end # String
|
|
50
|
+
end # Target
|
|
51
|
+
|
|
52
|
+
private_constant(*constants(false))
|
|
53
|
+
|
|
22
54
|
# Run CLI
|
|
23
55
|
#
|
|
24
56
|
# @param [Array<String>] arguments
|
|
25
57
|
#
|
|
26
|
-
# @return [
|
|
58
|
+
# @return [Integer]
|
|
27
59
|
# the exit status
|
|
28
60
|
#
|
|
29
61
|
# @api private
|
|
@@ -39,22 +71,22 @@ module Unparser
|
|
|
39
71
|
# @return [undefined]
|
|
40
72
|
#
|
|
41
73
|
# @api private
|
|
42
|
-
#
|
|
43
|
-
# ignore :reek:TooManyStatements
|
|
44
74
|
def initialize(arguments)
|
|
45
|
-
@
|
|
46
|
-
@
|
|
75
|
+
@ignore = Set.new
|
|
76
|
+
@targets = []
|
|
47
77
|
|
|
48
|
-
@
|
|
49
|
-
@
|
|
50
|
-
@
|
|
78
|
+
@fail_fast = false
|
|
79
|
+
@start_with = nil
|
|
80
|
+
@success = true
|
|
81
|
+
@validation = :validation
|
|
82
|
+
@verbose = false
|
|
51
83
|
|
|
52
84
|
opts = OptionParser.new do |builder|
|
|
53
85
|
add_options(builder)
|
|
54
86
|
end
|
|
55
87
|
|
|
56
88
|
opts.parse!(arguments).each do |name|
|
|
57
|
-
@
|
|
89
|
+
@targets.concat(targets(name))
|
|
58
90
|
end
|
|
59
91
|
end
|
|
60
92
|
|
|
@@ -66,38 +98,40 @@ module Unparser
|
|
|
66
98
|
#
|
|
67
99
|
# @api private
|
|
68
100
|
#
|
|
69
|
-
#
|
|
101
|
+
# rubocop:disable Metrics/MethodLength
|
|
70
102
|
def add_options(builder)
|
|
71
103
|
builder.banner = 'usage: unparse [options] FILE [FILE]'
|
|
72
104
|
builder.separator('')
|
|
73
105
|
builder.on('-e', '--evaluate SOURCE') do |source|
|
|
74
|
-
@
|
|
106
|
+
@targets << Target::String.new(source)
|
|
75
107
|
end
|
|
76
|
-
builder.on('--start-with FILE') do |
|
|
77
|
-
@start_with =
|
|
108
|
+
builder.on('--start-with FILE') do |path|
|
|
109
|
+
@start_with = targets(path).first
|
|
78
110
|
end
|
|
79
111
|
builder.on('-v', '--verbose') do
|
|
80
112
|
@verbose = true
|
|
81
113
|
end
|
|
114
|
+
builder.on('-l', '--literal') do
|
|
115
|
+
@validation = :literal_validation
|
|
116
|
+
end
|
|
82
117
|
builder.on('--ignore FILE') do |file|
|
|
83
|
-
@ignore.merge(
|
|
118
|
+
@ignore.merge(targets(file))
|
|
84
119
|
end
|
|
85
120
|
builder.on('--fail-fast') do
|
|
86
121
|
@fail_fast = true
|
|
87
122
|
end
|
|
88
123
|
end
|
|
124
|
+
# rubocop:enable Metrics/MethodLength
|
|
89
125
|
|
|
90
126
|
# Return exit status
|
|
91
127
|
#
|
|
92
|
-
# @return [
|
|
128
|
+
# @return [Integer]
|
|
93
129
|
#
|
|
94
130
|
# @api private
|
|
95
131
|
#
|
|
96
132
|
def exit_status
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
process_source(source)
|
|
133
|
+
effective_targets.each do |target|
|
|
134
|
+
process_target(target)
|
|
101
135
|
break if @fail_fast && !@success
|
|
102
136
|
end
|
|
103
137
|
|
|
@@ -106,67 +140,41 @@ module Unparser
|
|
|
106
140
|
|
|
107
141
|
private
|
|
108
142
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
#
|
|
115
|
-
# @api private
|
|
116
|
-
#
|
|
117
|
-
def process_source(source)
|
|
118
|
-
if source.success?
|
|
119
|
-
puts source.report if @verbose
|
|
120
|
-
puts "Success: #{source.identification}"
|
|
143
|
+
def process_target(target)
|
|
144
|
+
validation = target.public_send(@validation)
|
|
145
|
+
if validation.success?
|
|
146
|
+
puts validation.report if @verbose
|
|
147
|
+
puts "Success: #{validation.identification}"
|
|
121
148
|
else
|
|
122
|
-
puts
|
|
123
|
-
puts "Error: #{
|
|
149
|
+
puts validation.report
|
|
150
|
+
puts "Error: #{validation.identification}"
|
|
124
151
|
@success = false
|
|
125
152
|
end
|
|
126
153
|
end
|
|
127
154
|
|
|
128
|
-
|
|
129
|
-
#
|
|
130
|
-
# @return [Enumerable<CLI::Source>]
|
|
131
|
-
#
|
|
132
|
-
# @api private
|
|
133
|
-
#
|
|
134
|
-
def effective_sources
|
|
155
|
+
def effective_targets
|
|
135
156
|
if @start_with
|
|
136
157
|
reject = true
|
|
137
|
-
@
|
|
138
|
-
if reject &&
|
|
158
|
+
@targets.reject do |targets|
|
|
159
|
+
if reject && targets.eql?(@start_with)
|
|
139
160
|
reject = false
|
|
140
161
|
end
|
|
141
162
|
|
|
142
163
|
reject
|
|
143
164
|
end
|
|
144
165
|
else
|
|
145
|
-
@
|
|
146
|
-
end
|
|
166
|
+
@targets
|
|
167
|
+
end.reject(&@ignore.method(:include?))
|
|
147
168
|
end
|
|
148
169
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
# ignore :reek:UtilityFunction
|
|
158
|
-
def sources(file_name)
|
|
159
|
-
files =
|
|
160
|
-
if File.directory?(file_name)
|
|
161
|
-
Dir.glob(File.join(file_name, '**/*.rb')).sort
|
|
162
|
-
elsif File.file?(file_name)
|
|
163
|
-
[file_name]
|
|
164
|
-
else
|
|
165
|
-
Dir.glob(file_name).sort
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
files.map(&Source::File.method(:new))
|
|
170
|
+
def targets(file_name)
|
|
171
|
+
if File.directory?(file_name)
|
|
172
|
+
Dir.glob(File.join(file_name, '**/*.rb')).sort
|
|
173
|
+
elsif File.file?(file_name)
|
|
174
|
+
[file_name]
|
|
175
|
+
else
|
|
176
|
+
Dir.glob(file_name).sort
|
|
177
|
+
end.map { |file| Target::Path.new(Pathname.new(file)) }
|
|
169
178
|
end
|
|
170
|
-
|
|
171
179
|
end # CLI
|
|
172
180
|
end # Unparser
|
|
@@ -3,16 +3,13 @@
|
|
|
3
3
|
module Unparser
|
|
4
4
|
# Class to colorize strings
|
|
5
5
|
class Color
|
|
6
|
-
include Adamantium
|
|
6
|
+
include Adamantium, Concord.new(:code)
|
|
7
7
|
|
|
8
8
|
# Format text with color
|
|
9
9
|
#
|
|
10
10
|
# @param [String] text
|
|
11
11
|
#
|
|
12
12
|
# @return [String]
|
|
13
|
-
#
|
|
14
|
-
# @api private
|
|
15
|
-
#
|
|
16
13
|
def format(text)
|
|
17
14
|
"\e[#{code}m#{text}\e[0m"
|
|
18
15
|
end
|
|
@@ -25,28 +22,21 @@ module Unparser
|
|
|
25
22
|
#
|
|
26
23
|
# @return [String]
|
|
27
24
|
# the argument string
|
|
28
|
-
#
|
|
29
|
-
# @api private
|
|
30
|
-
#
|
|
31
25
|
def format(text)
|
|
32
26
|
text
|
|
33
27
|
end
|
|
34
28
|
|
|
35
29
|
private
|
|
36
30
|
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
# @return [undefined]
|
|
40
|
-
#
|
|
41
|
-
# @api private
|
|
42
|
-
#
|
|
31
|
+
# Well rubocop you are static so you do not have a clue here ;)
|
|
32
|
+
# rubocop:disable Style/RedundantInitialize
|
|
43
33
|
def initialize; end
|
|
34
|
+
# rubocop:enable Style/RedundantInitialize
|
|
44
35
|
|
|
45
36
|
end.new
|
|
46
37
|
|
|
47
38
|
RED = Color.new(31)
|
|
48
39
|
GREEN = Color.new(32)
|
|
49
|
-
BLUE = Color.new(34)
|
|
50
40
|
|
|
51
41
|
end # Color
|
|
52
42
|
end # Unparser
|