Skip to content

Commit d5e29dc

Browse files
committed
Add in place evaluation for test-unparser binary
1 parent 9dc6c51 commit d5e29dc

1 file changed

Lines changed: 131 additions & 15 deletions

File tree

bin/test-unparser

Lines changed: 131 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,137 @@ end
66

77
require 'unparser'
88
require 'parser/current'
9+
require 'mutant'
10+
require 'optparse'
911

10-
ARGV.each do |file|
11-
source = File.read(file)
12-
node = Parser::CurrentRuby.parse(source)
13-
generated = Unparser.unparse(node)
14-
unparsed = Parser::CurrentRuby.parse(generated)
15-
unless unparsed == node
16-
$stderr.puts 'Node:'
17-
$stderr.puts node.inspect
18-
$stderr.puts 'Unparsed-Node:'
19-
$stderr.puts unparsed.inspect
20-
$stderr.puts 'Original:'
21-
$stderr.puts source
22-
$stderr.puts 'Generated:'
23-
$stderr.puts generated
24-
fail 'BUG!'
12+
# Class to create diffs from source code
13+
class Differ < Mutant::Differ
14+
15+
def self.run(*arguments)
16+
new(*arguments).colorized_diff
17+
end
18+
19+
# Return source diff
20+
#
21+
# @return [String]
22+
# if there is a diff
23+
#
24+
# @return [nil]
25+
# otherwise
26+
#
27+
# @api private
28+
#
29+
def diff
30+
diffs.map do |piece|
31+
Diff::LCS::Hunk.new(old, new, piece, max_length, old.length - new.length).diff(:unified) << "\n"
32+
end.join
33+
end
34+
memoize :diff
35+
36+
end # Differ
37+
38+
class Unparse
39+
class Source
40+
include AbstractType, Adamantium::Flat
41+
42+
def success?
43+
original_ast == generated_ast
44+
end
45+
46+
def error_report
47+
report = []
48+
report << Differ.run(original_ast.inspect.lines.map(&:chomp), generated_ast.inspect.lines.map(&:chomp))
49+
report << 'Original:'
50+
report << original_ast.inspect
51+
report << original_source
52+
report << 'Generated:'
53+
report << generated_ast.inspect
54+
report << generated_source
55+
report.join("\n")
56+
end
57+
58+
private
59+
60+
def generated_source
61+
Unparser.unparse(original_ast)
62+
end
63+
memoize :generated_source
64+
65+
def generated_ast
66+
Parser::CurrentRuby.parse(generated_source)
67+
end
68+
memoize :generated_ast
69+
70+
def original_ast
71+
Parser::CurrentRuby.parse(original_source)
72+
end
73+
memoize :original_ast
74+
75+
class String < self
76+
include Concord.new(:original_source)
77+
78+
def identification
79+
'(evaluate)'
80+
end
81+
end
82+
83+
class File < self
84+
include Concord.new(:file_name)
85+
86+
def identification
87+
"(#{file_name})"
88+
end
89+
90+
private
91+
92+
def original_source
93+
::File.read(file_name)
94+
end
95+
memoize :original_source
96+
end
97+
end
98+
99+
def self.run(*arguments)
100+
new(*arguments).process
101+
end
102+
103+
def initialize(arguments)
104+
@sources = []
105+
106+
opts = OptionParser.new do |builder|
107+
builder.banner = 'usage: unparse [options] FILE [FILE]'
108+
builder.separator('')
109+
builder.on('-e', '--evaluate SOURCE') do |original_source|
110+
@sources << Source::String.new(original_source)
111+
end
112+
end
113+
114+
file_names =
115+
begin
116+
opts.parse!(arguments)
117+
rescue OptionParser::ParseError => error
118+
raise(Error, error.message, error.backtrace)
119+
end
120+
121+
file_names.each do |file_name|
122+
@sources << Source::File.new(file_name)
123+
end
124+
end
125+
126+
def process
127+
@sources.each do |source|
128+
process_source(source)
129+
end
130+
end
131+
132+
def process_source(source)
133+
if source.success?
134+
puts "Success: #{source.identification}"
135+
else
136+
puts source.error_report
137+
fail "Error: #{source.identification}"
138+
end
25139
end
26140
end
141+
142+
Unparse.run(ARGV)

0 commit comments

Comments
 (0)