unparser 0.4.7 → 0.5.2
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 +1 -2
- data/bin/unparser +1 -1
- data/lib/unparser.rb +134 -62
- data/lib/unparser/ast.rb +0 -1
- data/lib/unparser/ast/local_variable_scope.rb +6 -76
- data/lib/unparser/buffer.rb +19 -16
- data/lib/unparser/cli.rb +84 -77
- data/lib/unparser/{cli/color.rb → color.rb} +0 -13
- data/lib/unparser/comments.rb +0 -26
- data/lib/unparser/constants.rb +4 -53
- data/lib/unparser/diff.rb +98 -0
- data/lib/unparser/dsl.rb +0 -32
- data/lib/unparser/emitter.rb +24 -425
- data/lib/unparser/emitter/alias.rb +2 -8
- data/lib/unparser/emitter/args.rb +45 -0
- data/lib/unparser/emitter/argument.rb +8 -166
- 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/flipflop.rb +11 -10
- data/lib/unparser/emitter/float.rb +29 -0
- data/lib/unparser/emitter/flow_modifier.rb +8 -55
- data/lib/unparser/emitter/for.rb +5 -19
- data/lib/unparser/emitter/hash.rb +74 -0
- data/lib/unparser/emitter/hash_pattern.rb +67 -0
- data/lib/unparser/emitter/hookexe.rb +5 -11
- data/lib/unparser/emitter/if.rb +9 -73
- data/lib/unparser/emitter/in_match.rb +21 -0
- data/lib/unparser/emitter/in_pattern.rb +34 -0
- data/lib/unparser/emitter/index.rb +21 -88
- 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_rest.rb +26 -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 +12 -27
- 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 +2 -18
- 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/generation.rb +250 -0
- data/lib/unparser/node_details.rb +21 -0
- data/lib/unparser/node_details/send.rb +62 -0
- data/lib/unparser/node_helpers.rb +45 -6
- data/lib/unparser/validation.rb +172 -0
- data/lib/unparser/writer.rb +15 -0
- data/lib/unparser/writer/binary.rb +99 -0
- data/lib/unparser/writer/dynamic_string.rb +233 -0
- data/lib/unparser/writer/resbody.rb +40 -0
- data/lib/unparser/writer/rescue.rb +39 -0
- data/lib/unparser/writer/send.rb +124 -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
- metadata +127 -104
- 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.rb +0 -10
- 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/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
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,21 @@ 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
|
+
@success = true
|
|
80
|
+
@validation = :validation
|
|
81
|
+
@verbose = false
|
|
51
82
|
|
|
52
83
|
opts = OptionParser.new do |builder|
|
|
53
84
|
add_options(builder)
|
|
54
85
|
end
|
|
55
86
|
|
|
56
87
|
opts.parse!(arguments).each do |name|
|
|
57
|
-
@
|
|
88
|
+
@targets.concat(targets(name))
|
|
58
89
|
end
|
|
59
90
|
end
|
|
60
91
|
|
|
@@ -66,38 +97,40 @@ module Unparser
|
|
|
66
97
|
#
|
|
67
98
|
# @api private
|
|
68
99
|
#
|
|
69
|
-
#
|
|
100
|
+
# rubocop:disable Metrics/MethodLength
|
|
70
101
|
def add_options(builder)
|
|
71
102
|
builder.banner = 'usage: unparse [options] FILE [FILE]'
|
|
72
103
|
builder.separator('')
|
|
73
104
|
builder.on('-e', '--evaluate SOURCE') do |source|
|
|
74
|
-
@
|
|
105
|
+
@targets << Target::String.new(source)
|
|
75
106
|
end
|
|
76
|
-
builder.on('--start-with FILE') do |
|
|
77
|
-
@start_with =
|
|
107
|
+
builder.on('--start-with FILE') do |path|
|
|
108
|
+
@start_with = targets(path).first
|
|
78
109
|
end
|
|
79
110
|
builder.on('-v', '--verbose') do
|
|
80
111
|
@verbose = true
|
|
81
112
|
end
|
|
113
|
+
builder.on('-l', '--literal') do
|
|
114
|
+
@validation = :literal_validation
|
|
115
|
+
end
|
|
82
116
|
builder.on('--ignore FILE') do |file|
|
|
83
|
-
@ignore.merge(
|
|
117
|
+
@ignore.merge(targets(file))
|
|
84
118
|
end
|
|
85
119
|
builder.on('--fail-fast') do
|
|
86
120
|
@fail_fast = true
|
|
87
121
|
end
|
|
88
122
|
end
|
|
123
|
+
# rubocop:enable Metrics/MethodLength
|
|
89
124
|
|
|
90
125
|
# Return exit status
|
|
91
126
|
#
|
|
92
|
-
# @return [
|
|
127
|
+
# @return [Integer]
|
|
93
128
|
#
|
|
94
129
|
# @api private
|
|
95
130
|
#
|
|
96
131
|
def exit_status
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
process_source(source)
|
|
132
|
+
effective_targets.each do |target|
|
|
133
|
+
process_target(target)
|
|
101
134
|
break if @fail_fast && !@success
|
|
102
135
|
end
|
|
103
136
|
|
|
@@ -106,67 +139,41 @@ module Unparser
|
|
|
106
139
|
|
|
107
140
|
private
|
|
108
141
|
|
|
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}"
|
|
142
|
+
def process_target(target)
|
|
143
|
+
validation = target.public_send(@validation)
|
|
144
|
+
if validation.success?
|
|
145
|
+
puts validation.report if @verbose
|
|
146
|
+
puts "Success: #{validation.identification}"
|
|
121
147
|
else
|
|
122
|
-
puts
|
|
123
|
-
puts "Error: #{
|
|
148
|
+
puts validation.report
|
|
149
|
+
puts "Error: #{validation.identification}"
|
|
124
150
|
@success = false
|
|
125
151
|
end
|
|
126
152
|
end
|
|
127
153
|
|
|
128
|
-
|
|
129
|
-
#
|
|
130
|
-
# @return [Enumerable<CLI::Source>]
|
|
131
|
-
#
|
|
132
|
-
# @api private
|
|
133
|
-
#
|
|
134
|
-
def effective_sources
|
|
154
|
+
def effective_targets
|
|
135
155
|
if @start_with
|
|
136
156
|
reject = true
|
|
137
|
-
@
|
|
138
|
-
if reject &&
|
|
157
|
+
@targets.reject do |targets|
|
|
158
|
+
if reject && targets.eql?(@start_with)
|
|
139
159
|
reject = false
|
|
140
160
|
end
|
|
141
161
|
|
|
142
162
|
reject
|
|
143
163
|
end
|
|
144
164
|
else
|
|
145
|
-
@
|
|
146
|
-
end
|
|
165
|
+
@targets
|
|
166
|
+
end.reject(&@ignore.method(:include?))
|
|
147
167
|
end
|
|
148
168
|
|
|
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))
|
|
169
|
+
def targets(file_name)
|
|
170
|
+
if File.directory?(file_name)
|
|
171
|
+
Dir.glob(File.join(file_name, '**/*.rb')).sort
|
|
172
|
+
elsif File.file?(file_name)
|
|
173
|
+
[file_name]
|
|
174
|
+
else
|
|
175
|
+
Dir.glob(file_name).sort
|
|
176
|
+
end.map { |file| Target::Path.new(Pathname.new(file)) }
|
|
169
177
|
end
|
|
170
|
-
|
|
171
178
|
end # CLI
|
|
172
179
|
end # Unparser
|
|
@@ -10,9 +10,6 @@ module Unparser
|
|
|
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,18 @@ 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
|
-
# Initialize null color
|
|
38
|
-
#
|
|
39
|
-
# @return [undefined]
|
|
40
|
-
#
|
|
41
|
-
# @api private
|
|
42
|
-
#
|
|
43
31
|
def initialize; end
|
|
44
32
|
|
|
45
33
|
end.new
|
|
46
34
|
|
|
47
35
|
RED = Color.new(31)
|
|
48
36
|
GREEN = Color.new(32)
|
|
49
|
-
BLUE = Color.new(34)
|
|
50
37
|
|
|
51
38
|
end # Color
|
|
52
39
|
end # Unparser
|
data/lib/unparser/comments.rb
CHANGED
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
module Unparser
|
|
4
4
|
|
|
5
5
|
# Holds the comments that remain to be emitted
|
|
6
|
-
#
|
|
7
|
-
# ignore :reek:RepeatedConditional
|
|
8
6
|
class Comments
|
|
9
7
|
|
|
10
8
|
# Proxy to singleton
|
|
@@ -113,39 +111,15 @@ module Unparser
|
|
|
113
111
|
|
|
114
112
|
private
|
|
115
113
|
|
|
116
|
-
# Take comments while the provided block returns true
|
|
117
|
-
#
|
|
118
|
-
# @yield [Parser::Source::Comment]
|
|
119
|
-
#
|
|
120
|
-
# @return [Array]
|
|
121
|
-
#
|
|
122
|
-
# @api private
|
|
123
|
-
#
|
|
124
114
|
def take_while
|
|
125
115
|
number_to_take = @comments.index { |comment| !yield(comment) } || @comments.size
|
|
126
116
|
@comments.shift(number_to_take)
|
|
127
117
|
end
|
|
128
118
|
|
|
129
|
-
# Take comments up to the line number
|
|
130
|
-
#
|
|
131
|
-
# @param [Fixnum] line
|
|
132
|
-
#
|
|
133
|
-
# @return [Array]
|
|
134
|
-
#
|
|
135
|
-
# @api private
|
|
136
|
-
#
|
|
137
119
|
def take_up_to_line(line)
|
|
138
120
|
take_while { |comment| comment.location.expression.line <= line }
|
|
139
121
|
end
|
|
140
122
|
|
|
141
|
-
# Unshift document comments and return the rest
|
|
142
|
-
#
|
|
143
|
-
# @param [Array] comments
|
|
144
|
-
#
|
|
145
|
-
# @return [Array]
|
|
146
|
-
#
|
|
147
|
-
# @api private
|
|
148
|
-
#
|
|
149
123
|
def unshift_documents(comments)
|
|
150
124
|
doc_comments, other_comments = comments.partition(&:document?)
|
|
151
125
|
doc_comments.reverse_each { |comment| @comments.unshift(comment) }
|
data/lib/unparser/constants.rb
CHANGED
|
@@ -2,66 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
module Unparser
|
|
4
4
|
# All unparser constants maybe included in other libraries.
|
|
5
|
-
#
|
|
6
|
-
# False positive since constants are frozen dynamically
|
|
7
|
-
# to avoid duplication of `.freeze` calls
|
|
8
|
-
#
|
|
9
|
-
# :reek:TooManyConstants
|
|
10
5
|
module Constants
|
|
11
6
|
|
|
12
|
-
# Return frozen symbol set from enumerable
|
|
13
|
-
#
|
|
14
|
-
# @param [Enumerable] enumerable
|
|
15
|
-
#
|
|
16
|
-
# @return [Set<Symbol>]
|
|
17
|
-
#
|
|
18
|
-
# @api private
|
|
19
|
-
#
|
|
20
|
-
def self.symbol_set(enumerable)
|
|
21
|
-
enumerable.map(&:to_sym).freeze
|
|
22
|
-
end
|
|
23
|
-
private_class_method :symbol_set
|
|
24
|
-
|
|
25
|
-
BRACKETS_CURLY = IceNine.deep_freeze(%w[{ }])
|
|
26
|
-
BRACKETS_ROUND = IceNine.deep_freeze(%w[( )])
|
|
27
|
-
BRACKETS_SQUARE = IceNine.deep_freeze(%w([ ]))
|
|
28
|
-
|
|
29
7
|
# All unary operators of the ruby language
|
|
30
|
-
UNARY_OPERATORS =
|
|
8
|
+
UNARY_OPERATORS = %i[
|
|
31
9
|
! ~ -@ +@
|
|
32
|
-
]
|
|
10
|
+
].to_set.freeze
|
|
33
11
|
|
|
34
12
|
# All binary operators of the ruby language
|
|
35
|
-
BINARY_OPERATORS =
|
|
13
|
+
BINARY_OPERATORS = %i[
|
|
36
14
|
+ - * / & | && || << >> ==
|
|
37
15
|
=== != <= < <=> > >= =~ !~ ^
|
|
38
16
|
** %
|
|
39
|
-
]
|
|
40
|
-
|
|
41
|
-
COMMENT = '#'
|
|
42
|
-
|
|
43
|
-
WS = ' '
|
|
44
|
-
NL = "\n"
|
|
45
|
-
T_DOT = '.'
|
|
46
|
-
T_LT = '<'
|
|
47
|
-
T_DLT = '<<'
|
|
48
|
-
T_AMP = '&'
|
|
49
|
-
T_ASN = '='
|
|
50
|
-
T_SPLAT = '*'
|
|
51
|
-
T_DSPLAT = '**'
|
|
52
|
-
T_ASR = '=>'
|
|
53
|
-
T_PIPE = '|'
|
|
54
|
-
T_DCL = '::'
|
|
55
|
-
T_NEG = '!'
|
|
56
|
-
T_OR = '||'
|
|
57
|
-
T_AND = '&&'
|
|
58
|
-
T_COLON = ':'
|
|
59
|
-
|
|
60
|
-
M_PO = '('
|
|
61
|
-
M_PC = ')'
|
|
62
|
-
|
|
63
|
-
SNGL_QUOTE = "'"
|
|
64
|
-
DBL_QUOTE = '"'
|
|
17
|
+
].to_set.freeze
|
|
65
18
|
|
|
66
19
|
# Keywords
|
|
67
20
|
K_DO = 'do'
|
|
@@ -107,8 +60,6 @@ module Unparser
|
|
|
107
60
|
K_FILE = '__FILE__'
|
|
108
61
|
K_THEN = 'then'
|
|
109
62
|
|
|
110
|
-
DEFAULT_DELIMITER = ', '.freeze
|
|
111
|
-
|
|
112
63
|
KEYWORDS = constants.each_with_object([]) do |name, keywords|
|
|
113
64
|
value = const_get(name).freeze
|
|
114
65
|
next unless name.to_s.start_with?('K_')
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
# Class to create diffs from source code
|
|
5
|
+
class Diff
|
|
6
|
+
include Adamantium::Flat, Concord.new(:old, :new)
|
|
7
|
+
|
|
8
|
+
ADDITION = '+'
|
|
9
|
+
DELETION = '-'
|
|
10
|
+
NEWLINE = "\n"
|
|
11
|
+
|
|
12
|
+
# Unified source diff between old and new
|
|
13
|
+
#
|
|
14
|
+
# @return [String]
|
|
15
|
+
# if there is exactly one diff
|
|
16
|
+
#
|
|
17
|
+
# @return [nil]
|
|
18
|
+
# otherwise
|
|
19
|
+
def diff
|
|
20
|
+
return if diffs.empty?
|
|
21
|
+
|
|
22
|
+
minimized_hunk.diff(:unified) + NEWLINE
|
|
23
|
+
end
|
|
24
|
+
memoize :diff
|
|
25
|
+
|
|
26
|
+
# Colorized unified source diff between old and new
|
|
27
|
+
#
|
|
28
|
+
# @return [String]
|
|
29
|
+
# if there is a diff
|
|
30
|
+
#
|
|
31
|
+
# @return [nil]
|
|
32
|
+
# otherwise
|
|
33
|
+
def colorized_diff
|
|
34
|
+
return unless diff
|
|
35
|
+
|
|
36
|
+
diff.lines.map(&self.class.method(:colorize_line)).join
|
|
37
|
+
end
|
|
38
|
+
memoize :colorized_diff
|
|
39
|
+
|
|
40
|
+
# Build new object from source strings
|
|
41
|
+
#
|
|
42
|
+
# @param [String] old
|
|
43
|
+
# @param [String] new
|
|
44
|
+
#
|
|
45
|
+
# @return [Diff]
|
|
46
|
+
def self.build(old, new)
|
|
47
|
+
new(lines(old), lines(new))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Break up source into lines
|
|
51
|
+
#
|
|
52
|
+
# @param [String] source
|
|
53
|
+
#
|
|
54
|
+
# @return [Array<String>]
|
|
55
|
+
def self.lines(source)
|
|
56
|
+
source.lines.map(&:chomp)
|
|
57
|
+
end
|
|
58
|
+
private_class_method :lines
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def diffs
|
|
63
|
+
::Diff::LCS.diff(old, new)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def hunks
|
|
67
|
+
diffs.map do |diff|
|
|
68
|
+
::Diff::LCS::Hunk.new(old.map(&:dup), new, diff, max_length, 0)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def minimized_hunk
|
|
73
|
+
head, *tail = hunks
|
|
74
|
+
|
|
75
|
+
tail.reduce(head) do |left, right|
|
|
76
|
+
right.merge(left)
|
|
77
|
+
right
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def max_length
|
|
82
|
+
[old, new].map(&:length).max
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def self.colorize_line(line)
|
|
86
|
+
case line[0]
|
|
87
|
+
when ADDITION
|
|
88
|
+
Color::GREEN
|
|
89
|
+
when DELETION
|
|
90
|
+
Color::RED
|
|
91
|
+
else
|
|
92
|
+
Color::NONE
|
|
93
|
+
end.format(line)
|
|
94
|
+
end
|
|
95
|
+
private_class_method :colorize_line
|
|
96
|
+
|
|
97
|
+
end # Diff
|
|
98
|
+
end # Unparser
|