forked from fables-tales/rubyfmt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest.rb
177 lines (143 loc) · 3.87 KB
/
test.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
$: << File.dirname(__FILE__)
require "rubyfmt.so"
require "ripper"
require "json"
class Parser < Ripper::SexpBuilderPP
ARRAY_SYMBOLS = {qsymbols: "%i", qwords: "%w", symbols: "%I", words: "%W"}.freeze
def self.is_percent_array?(rest)
return false if rest.nil?
return false if rest[0].nil?
ARRAY_SYMBOLS.include?(rest[0][0])
end
def self.percent_symbol_for(rest)
ARRAY_SYMBOLS[rest[0][0]]
end
def initialize(file_data)
super(file_data)
@file_lines = file_data.split("\n")
# heredoc stack is the stack of identified heredocs
@heredoc_stack = []
# next_heredoc_stack is the type identifiers of the next heredocs, that
# we haven't emitted yet
@next_heredoc_stack = []
@heredoc_regex = /(<<[-~]?)(.*$)/
@next_comment_delete = []
@comments_delete = []
@regexp_stack = []
@string_stack = []
@kw_stacks = {
"return" => [],
"when" => [],
"yield" => [],
"break" => [],
}
@array_location_stacks = []
end
attr_reader :comments_delete
private
ARRAY_SYMBOLS.each do |event, symbol|
define_method(:"on_#{event}_new") do
[event, [], [lineno, column]]
end
define_method(:"on_#{event}_add") do |parts, part|
parts.tap do |node|
node[1] << part
end
end
end
def on_lbracket(*args)
@array_location_stacks << [lineno, column]
end
def on_array(*args)
res = super
res << @array_location_stacks.pop
res
end
def on_kw(kw)
if stack = @kw_stacks[kw]
stack << [lineno, column]
end
super
end
def on_return(args)
[:return, args, @kw_stacks["return"].pop]
end
def on_when(cond, body, tail)
[:when, cond, body, tail, @kw_stacks["when"].pop]
end
def on_yield(arg)
[:yield, arg, @kw_stacks["yield"].pop]
end
def on_break(arg)
[:break, arg, @kw_stacks["break"].pop]
end
def on_heredoc_beg(*args, &blk)
heredoc_parts = @heredoc_regex.match(args[0]).captures
raise "bad heredoc" unless heredoc_parts.select { |x| x != nil }.count == 2
@next_heredoc_stack.push(heredoc_parts)
@next_comment_delete.push(lineno)
super
end
def on_heredoc_end(*args, &blk)
@heredoc_stack.push(@next_heredoc_stack.pop)
start_com = @next_comment_delete.pop
end_com = lineno
@comments_delete.push([start_com, end_com])
super
end
def on_string_literal(*args, &blk)
if @heredoc_stack.last
heredoc_parts = @heredoc_stack.pop
args.insert(0, [:heredoc_string_literal, heredoc_parts])
else
end_delim = @string_stack.pop
start_delim = @string_stack.pop
if start_delim != "\""
reject_embexpr = start_delim == "'" || start_delim.start_with?("%q")
(args[0][1..-1] || []).each do |part|
next if part.nil?
case part[0]
when :@tstring_content
part[1] = eval("#{start_delim}#{part[1]}#{end_delim}").inspect[1..-2]
when :string_embexpr, :string_dvar
if reject_embexpr
raise "got #{part[0]} in a #{start_delim}...#{end_delim} string"
end
else
raise "got #{part[0]} in a #{start_delim}...#{end_delim} string"
end
end
end
end
super
end
def on_lambda(*args, &blk)
terminator = @file_lines[lineno - 1]
if terminator.include?("}")
args.insert(1, :curly)
else
args.insert(1, :do)
end
super
end
def on_tstring_beg(*args, &blk)
@string_stack << args[0]
super
end
def on_tstring_end(*args, &blk)
@string_stack << args[0]
super
end
def on_regexp_beg(re_part)
@regexp_stack << re_part
end
def on_regexp_literal(*args)
args[1] << @regexp_stack.pop
super(*args)
end
end
file_data = File.read(ARGV[0])
parsed = Parser.new(file_data).parse
inspected_parsed = JSON.dump(parsed)
Rubyfmt::format_to_stdout(file_data, inspected_parsed)
STDOUT.close