unparser 0.4.7 → 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,152 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Unparser
4
- class CLI
5
- # Class to create diffs from source code
6
- class Differ
7
- include Adamantium::Flat, Concord.new(:old, :new), Procto.call(:colorized_diff)
8
-
9
- CONTEXT_LINES = 5
10
-
11
- # Return new object
12
- #
13
- # @param [String] old
14
- # @param [String] new
15
- #
16
- # @return [Differ]
17
- #
18
- # @api private
19
- #
20
- def self.build(old, new)
21
- new(lines(old), lines(new))
22
- end
23
-
24
- # Return colorized diff line
25
- #
26
- # @param [String] line
27
- #
28
- # @return [String]
29
- #
30
- # @api private
31
- #
32
- def self.colorize_line(line)
33
- case line[0]
34
- when '+'
35
- Color::GREEN
36
- when '-'
37
- Color::RED
38
- else
39
- Color::NONE
40
- end.format(line)
41
- end
42
-
43
- # Break up source into lines
44
- #
45
- # @param [String] source
46
- #
47
- # @return [Array<String>]
48
- #
49
- # @api private
50
- #
51
- def self.lines(source)
52
- source.lines.map(&:chomp)
53
- end
54
- private_class_method :lines
55
-
56
- # Return hunks
57
- #
58
- # @return [Array<Diff::LCS::Hunk>]
59
- #
60
- # @api private
61
- #
62
- def hunks
63
- file_length_difference = new.length - old.length
64
- diffs.map do |piece|
65
- hunk = Diff::LCS::Hunk.new(old, new, piece, CONTEXT_LINES, file_length_difference)
66
- file_length_difference = hunk.file_length_difference
67
- hunk
68
- end
69
- end
70
-
71
- # Return collapsed hunks
72
- #
73
- # @return [Enumerable<Diff::LCS::Hunk>]
74
- #
75
- # @api private
76
- #
77
- def collapsed_hunks
78
- hunks.each_with_object([]) do |hunk, output|
79
- last = output.last
80
-
81
- if last && hunk.merge(last)
82
- output.pop
83
- end
84
-
85
- output << hunk
86
- end
87
- end
88
-
89
- # Return source diff
90
- #
91
- # @return [String]
92
- # if there is a diff
93
- #
94
- # @return [nil]
95
- # otherwise
96
- #
97
- # @api private
98
- #
99
- def diff
100
- output = +''
101
-
102
- collapsed_hunks.each do |hunk|
103
- output << hunk.diff(:unified) << "\n"
104
- end
105
-
106
- output
107
- end
108
- memoize :diff
109
-
110
- # Return colorized source diff
111
- #
112
- # @return [String]
113
- # if there is a diff
114
- #
115
- # @return [nil]
116
- # otherwise
117
- #
118
- # @api private
119
- #
120
- def colorized_diff
121
- diff.lines.map do |line|
122
- self.class.colorize_line(line)
123
- end.join
124
- end
125
- memoize :colorized_diff
126
-
127
- private
128
-
129
- # Return diffs
130
- #
131
- # @return [Array<Array>]
132
- #
133
- # @api private
134
- #
135
- def diffs
136
- Diff::LCS.diff(old, new)
137
- end
138
- memoize :diffs
139
-
140
- # Return max length
141
- #
142
- # @return [Fixnum]
143
- #
144
- # @api private
145
- #
146
- def max_length
147
- [old, new].map(&:length).max
148
- end
149
-
150
- end # CLI
151
- end # Differ
152
- end # Unparser
@@ -1,267 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Unparser
4
- class CLI
5
- # Source representation for CLI sources
6
- #
7
- # ignore :reek:TooManyMethods
8
- class Source
9
- include AbstractType, Adamantium::Flat, NodeHelpers
10
-
11
- # Source state generated after first unparse
12
- class Generated
13
- include Concord::Public.new(:source, :ast, :error)
14
-
15
- # Test if source was generated successfully
16
- #
17
- # @return [Boolean]
18
- #
19
- # @api private
20
- #
21
- def success?
22
- !error
23
- end
24
-
25
- # Build generated source
26
- #
27
- # @param [Parser::AST::Node] ast
28
- #
29
- # @api private
30
- #
31
- def self.build(ast)
32
- source = Unparser.unparse(ast)
33
- new(source, ast, nil)
34
- rescue StandardError => exception
35
- new(nil, ast, exception)
36
- end
37
- end
38
-
39
- # Test if source could be unparsed successfully
40
- #
41
- # @return [Boolean]
42
- #
43
- # @api private
44
- #
45
- def success?
46
- generated.success? && original_ast && generated_ast && original_ast.eql?(generated_ast)
47
- end
48
-
49
- # Return error report
50
- #
51
- # @return [String]
52
- #
53
- # @api private
54
- #
55
- def report
56
- if original_ast && generated_ast
57
- report_with_ast_diff
58
- elsif !original_ast
59
- report_original
60
- elsif !generated.success?
61
- report_unparser
62
- elsif !generated_ast
63
- report_generated
64
- else
65
- raise
66
- end
67
- end
68
- memoize :report
69
-
70
- private
71
-
72
- # Return generated source
73
- #
74
- # @return [String]
75
- #
76
- # @api private
77
- #
78
- def generated
79
- Source::Generated.build(original_ast)
80
- end
81
- memoize :generated
82
-
83
- # Return stripped source
84
- #
85
- # @param [String] source
86
- #
87
- # @return [String]
88
- #
89
- # @api private
90
- #
91
- # ignore :reek:UtilityFunction
92
- def strip(source)
93
- source = source.rstrip
94
- indent = source.scan(/^\s*/).first
95
- source.gsub(/^#{indent}/, '')
96
- end
97
-
98
- # Return error report for parsing original
99
- #
100
- # @return [String]
101
- #
102
- # @api private
103
- #
104
- def report_original
105
- strip(<<-MESSAGE)
106
- Parsing of original source failed:
107
- #{original_source}
108
- MESSAGE
109
- end
110
-
111
- # Report unparser bug
112
- #
113
- # @return [String]
114
- #
115
- # @api private
116
- #
117
- def report_unparser
118
- message = ['Unparsing parsed AST failed']
119
- error = generated.error
120
- message << error
121
- error.backtrace.take(20).each(&message.method(:<<))
122
- message << 'Original-AST:'
123
- message << original_ast.inspect
124
- message.join("\n")
125
- end
126
-
127
- # Return error report for parsing generated
128
- #
129
- # @return [String]
130
- #
131
- # @api private
132
- #
133
- def report_generated
134
- strip(<<-MESSAGE)
135
- Parsing of generated source failed:
136
- Original-source:
137
- #{original_source}
138
- Original-AST:
139
- #{original_ast.inspect}
140
- Source:
141
- #{generated.source}
142
- MESSAGE
143
- end
144
-
145
- # Return error report with AST difference
146
- #
147
- # @return [String]
148
- #
149
- # @api private
150
- #
151
- def report_with_ast_diff
152
- strip(<<-MESSAGE)
153
- #{ast_diff}
154
- Original-Source:\n#{original_source}
155
- Original-AST:\n#{original_ast.inspect}
156
- Generated-Source:\n#{generated.source}
157
- Generated-AST:\n#{generated_ast.inspect}
158
- MESSAGE
159
- end
160
-
161
- # Return ast diff
162
- #
163
- # @return [String]
164
- #
165
- # @api private
166
- #
167
- def ast_diff
168
- Differ.call(
169
- original_ast.inspect.lines.map(&:chomp),
170
- generated_ast.inspect.lines.map(&:chomp)
171
- )
172
- end
173
-
174
- # Return generated AST
175
- #
176
- # @return [Parser::AST::Node]
177
- # if parser was sucessful for generated ast
178
- #
179
- # @return [nil]
180
- # otherwise
181
- #
182
- # @api private
183
- #
184
- def generated_ast
185
- generated.success? && Preprocessor.run(Unparser.parse(generated.source))
186
- rescue Parser::SyntaxError
187
- nil
188
- end
189
- memoize :generated_ast
190
-
191
- # Return original AST
192
- #
193
- # @return [Parser::AST::Node]
194
- #
195
- # @api private
196
- #
197
- def original_ast
198
- Preprocessor.run(Unparser.parse(original_source))
199
- rescue Parser::SyntaxError
200
- nil
201
- end
202
- memoize :original_ast
203
-
204
- # CLI source from string
205
- class String < self
206
- include Concord.new(:original_source)
207
-
208
- # Return identification
209
- #
210
- # @return [String]
211
- #
212
- # @api private
213
- #
214
- def identification
215
- '(string)'
216
- end
217
-
218
- end # String
219
-
220
- # CLI source from file
221
- class File < self
222
- include Concord.new(:file_name)
223
-
224
- # Return identification
225
- #
226
- # @return [String]
227
- #
228
- # @api private
229
- #
230
- def identification
231
- "(#{file_name})"
232
- end
233
-
234
- private
235
-
236
- # Return original source
237
- #
238
- # @return [String]
239
- #
240
- # @api private
241
- #
242
- def original_source
243
- ::File.read(file_name)
244
- end
245
- memoize :original_source
246
-
247
- end # File
248
-
249
- # Source passed in as node
250
- class Node < self
251
- include Concord.new(:original_ast)
252
-
253
- # Return original source
254
- #
255
- # @return [String]
256
- #
257
- # @api private
258
- #
259
- def original_source
260
- Unparser.unparse(original_ast)
261
- end
262
- memoize :original_source
263
- end # Node
264
-
265
- end # Source
266
- end # CLI
267
- end # Unparser