unparser 0.5.1 → 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5edf8f2731473b62649c92936d8c04ff8a19e598bdc9811feb332d8cd3cff58f
4
- data.tar.gz: 8e47978900270932616a7c7b1a8869442d0d0e64c90a6147b7bd6d0938edea44
3
+ metadata.gz: 21e418840b351f5e697c472127300d7733ca1c20bdf4be321ae1832133447767
4
+ data.tar.gz: c130412892dcb6a1db4835c3ef9fa9738f2a181ede78ccca6a7a13336a348e8c
5
5
  SHA512:
6
- metadata.gz: d5966f2f944ee5f596a3919d9c6d6b1ce1406ba4ab015b39d220941f35c4c5e5aeb401c270dab0b60883bd8b5fb3379d7dafe28be657a4af9fa4045be784a6f4
7
- data.tar.gz: 837b201d4d4ea307cbdc50d04640957618f6ccec1e7d5782b5b3654901369d80f02425d5c4a9b61cb1f90fb87d14146fff4889b7b1d49039369d58fdc33aa7d8
6
+ metadata.gz: 4a25a3e71df443024af556d20ca97f9a627874ee5857a4badfa2c7bd228159732fac0060715b198acc5648879c25baf8c0b10496f6cb0303fa41841cf06521ad
7
+ data.tar.gz: 8dec6ae089dbf574a7687177993da010f2569677217032e95079e007598c04e0acbb35d967667532331187d6ab25c81346c5073454dda7665e8864fc0e31e42a
data/README.md CHANGED
@@ -4,7 +4,7 @@ unparser
4
4
  ![CI](https://github.com/mbj/unparser/workflows/CI/badge.svg)
5
5
  [![Gem Version](https://img.shields.io/gem/v/unparser.svg)](https://rubygems.org/gems/unparser)
6
6
 
7
- Generate equivalent source for ASTs from whitequarks [parser](https://github.com/whitequark/parser).
7
+ Generate equivalent source for ASTs from [parser](https://github.com/whitequark/parser).
8
8
 
9
9
  The following constraints apply:
10
10
 
@@ -12,8 +12,13 @@ The following constraints apply:
12
12
  * Only support for the [modern AST](https://github.com/whitequark/parser/#usage) format
13
13
  * Only support for Ruby >= 2.5
14
14
 
15
- It serves well for [mutant](https://github.com/mbj/mutant) mutators and the in-memory vendoring for self hosting,
16
- and other tooling.
15
+ Notable Users:
16
+
17
+ * [mutant](https://github.com/mbj/mutant) - Code review engine via mutation testing.
18
+ * [ruby-next](https://github.com/ruby-next/ruby-next) - Ruby Syntax Backports.
19
+ * May other [reverse-dependencies](https://rubygems.org/gems/unparser/reverse_dependencies).
20
+
21
+ (if you want your tool to be mentioned here please PR the addition with a TLDR of your use case).
17
22
 
18
23
  Public API:
19
24
  -----------
@@ -86,12 +91,22 @@ RUBY
86
91
 
87
92
  generated = Unparser.unparse(node) # ["foo", "bar"], NOT %w[foo bar] !
88
93
 
89
- code == generated # false, not identical code
94
+ code == generated # false, not identical code
90
95
  Unparser.parse(generated) == node # true, but identical AST
91
96
  ```
92
97
 
93
98
  Summary: unparser does not reproduce your source! It produces equivalent source.
94
99
 
100
+ Ruby Versions:
101
+ --------------
102
+
103
+ Unparsers primay reason for existance is mutant and its
104
+ supported [Ruby-Versions](https://github.com/mbj/mutant#ruby-versions).
105
+
106
+ Basically: All non EOL MRI releases.
107
+
108
+ If you need to generate Ruby Syntax outside of this band feel free to contact me (email in gemspec).
109
+
95
110
  Testing:
96
111
  --------
97
112
 
@@ -50,6 +50,23 @@ module Unparser
50
50
  end.content
51
51
  end
52
52
 
53
+ # Unparse with validation
54
+ #
55
+ # @param [Parser::AST::Node, nil] node
56
+ # @param [Array] comment_array
57
+ #
58
+ # @return [Either<Validation,String>]
59
+ def self.unparse_validate(node, comment_array = [])
60
+ generated = unparse(node, comment_array)
61
+ validation = Validation.from_string(generated)
62
+
63
+ if validation.success?
64
+ MPrelude::Either::Right.new(generated)
65
+ else
66
+ MPrelude::Either::Left.new(validation)
67
+ end
68
+ end
69
+
53
70
  # Unparse capturing errors
54
71
  #
55
72
  # This is mostly useful for writing testing tools against unparser.
@@ -100,21 +117,10 @@ module Unparser
100
117
  Parser::CurrentRuby.new(Builder.new).tap do |parser|
101
118
  parser.diagnostics.tap do |diagnostics|
102
119
  diagnostics.all_errors_are_fatal = true
103
- diagnostics.consumer = method(:consume_diagnostic)
104
120
  end
105
121
  end
106
122
  end
107
123
 
108
- # Consume diagnostic
109
- #
110
- # @param [Parser::Diagnostic] diagnostic
111
- #
112
- # @return [undefined]
113
- def self.consume_diagnostic(diagnostic)
114
- Kernel.warn(diagnostic.render)
115
- end
116
- private_class_method :consume_diagnostic
117
-
118
124
  # Construct a parser buffer from string
119
125
  #
120
126
  # @param [String] source
@@ -192,6 +198,9 @@ require 'unparser/emitter/undef'
192
198
  require 'unparser/emitter/variable'
193
199
  require 'unparser/emitter/xstr'
194
200
  require 'unparser/emitter/yield'
201
+ require 'unparser/emitter/kwargs'
202
+ require 'unparser/emitter/pair'
203
+ require 'unparser/emitter/match_pattern'
195
204
  require 'unparser/writer'
196
205
  require 'unparser/writer/binary'
197
206
  require 'unparser/writer/dynamic_string'
@@ -19,8 +19,11 @@ module Unparser
19
19
  def dispatch
20
20
  write(MAP.fetch(node.type))
21
21
 
22
- unless children.empty?
23
- emit_arguments
22
+ if children.one? && n_if?(children.first)
23
+ ws
24
+ emitter(children.first).emit_ternary
25
+ else
26
+ emit_arguments unless children.empty?
24
27
  end
25
28
  end
26
29
 
@@ -4,10 +4,6 @@ module Unparser
4
4
  class Emitter
5
5
  # Emitter for Hash literals
6
6
  class Hash < self
7
- BAREWORD = /\A[A-Za-z_][A-Za-z_0-9]*[?!]?\z/.freeze
8
-
9
- private_constant(*constants(false))
10
-
11
7
  handle :hash
12
8
 
13
9
  def emit_last_argument_hash
@@ -41,34 +37,8 @@ module Unparser
41
37
  end
42
38
 
43
39
  def emit_hash_body
44
- delimited(children, &method(:emit_hash_member))
45
- end
46
-
47
- def emit_hash_member(node)
48
- if n_kwsplat?(node)
49
- visit(node)
50
- else
51
- emit_pair(node)
52
- end
40
+ delimited(children)
53
41
  end
54
-
55
- def emit_pair(pair)
56
- key, value = *pair.children
57
-
58
- if colon?(key)
59
- write(key.children.first.to_s, ': ')
60
- else
61
- visit(key)
62
- write(' => ')
63
- end
64
-
65
- visit(value)
66
- end
67
-
68
- def colon?(key)
69
- n_sym?(key) && BAREWORD.match?(key.children.first)
70
- end
71
-
72
42
  end # Hash
73
43
  end # Emitter
74
44
  end # Unparser
@@ -8,6 +8,14 @@ module Unparser
8
8
 
9
9
  children :condition, :if_branch, :else_branch
10
10
 
11
+ def emit_ternary
12
+ visit(condition)
13
+ write(' ? ')
14
+ visit(if_branch)
15
+ write(' : ')
16
+ visit(else_branch)
17
+ end
18
+
11
19
  private
12
20
 
13
21
  def dispatch
@@ -27,6 +27,8 @@ module Unparser
27
27
  ws
28
28
  write('then')
29
29
  emit_body(branch)
30
+ else
31
+ nl
30
32
  end
31
33
  end
32
34
  end # InPattern
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unparser
4
+ class Emitter
5
+ class Kwargs < self
6
+ handle :kwargs
7
+
8
+ def dispatch
9
+ delimited(children)
10
+ end
11
+ end # Kwargs
12
+ end # Emitter
13
+ end # Unparser
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unparser
4
+ class Emitter
5
+ # Emitter for in pattern nodes
6
+ class MatchPattern < self
7
+
8
+ handle :match_pattern
9
+ handle :match_pattern_p
10
+
11
+ children :target, :pattern
12
+
13
+ private
14
+
15
+ def dispatch
16
+ visit(target)
17
+ write(' in ')
18
+ visit(pattern)
19
+ end
20
+ end # InPattern
21
+ end # Emitter
22
+ end # Unparser
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unparser
4
+ class Emitter
5
+ # Emitter for key value pairs in hash literals or kwargs
6
+ class Pair < self
7
+ BAREWORD = /\A[A-Za-z_][A-Za-z_0-9]*[?!]?\z/.freeze
8
+
9
+ private_constant(*constants(false))
10
+
11
+ handle :pair
12
+
13
+ children :key, :value
14
+
15
+ private
16
+
17
+ def dispatch
18
+ if colon?(key)
19
+ write(key.children.first.to_s, ': ')
20
+ else
21
+ visit(key)
22
+ write(' => ')
23
+ end
24
+
25
+ visit(value)
26
+ end
27
+
28
+ def colon?(key)
29
+ n_sym?(key) && BAREWORD.match?(key.children.first)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -22,12 +22,22 @@ module Unparser
22
22
 
23
23
  children :subject
24
24
 
25
+ def emit_mlhs
26
+ write('*')
27
+ subject_emitter.emit_mlhs if subject
28
+ end
29
+
25
30
  private
26
31
 
27
32
  def dispatch
28
33
  write('*')
29
- visit(subject) if subject
34
+ subject_emitter.write_to_buffer
35
+ end
36
+
37
+ def subject_emitter
38
+ emitter(subject)
30
39
  end
40
+ memoize :subject_emitter
31
41
  end
32
42
  end
33
43
  end # Unparser
@@ -204,7 +204,9 @@ module Unparser
204
204
  end
205
205
 
206
206
  def emit_rescue_postcontrol(node)
207
- writer_with(Writer::Rescue, node).emit_postcontrol
207
+ writer = writer_with(Writer::Rescue, node)
208
+ writer.emit_postcontrol
209
+ writer.emit_heredoc_reminders
208
210
  end
209
211
 
210
212
  def emit_rescue_regular(node)
@@ -45,6 +45,7 @@ module Unparser
45
45
  ensure
46
46
  hash
47
47
  hash_pattern
48
+ if
48
49
  in_pattern
49
50
  int
50
51
  kwsplat
@@ -71,6 +71,27 @@ module Unparser
71
71
  )
72
72
  end
73
73
 
74
+ # Create validator from node
75
+ #
76
+ # @param [Parser::AST::Node] original_node
77
+ #
78
+ # @return [Validator]
79
+ def self.from_node(original_node)
80
+ generated_source = Unparser.unparse_either(original_node)
81
+
82
+ generated_node = generated_source
83
+ .lmap(&method(:const_unit))
84
+ .bind(&Unparser.public_method(:parse_either))
85
+
86
+ new(
87
+ identification: '(string)',
88
+ original_source: generated_source,
89
+ original_node: MPrelude::Either::Right.new(original_node),
90
+ generated_source: generated_source,
91
+ generated_node: generated_node
92
+ )
93
+ end
94
+
74
95
  # Create validator from file
75
96
  #
76
97
  # @param [Pathname] path
@@ -20,7 +20,7 @@ module Unparser
20
20
  ]
21
21
  )
22
22
 
23
- FLAT_INTERPOLATION = %i[ivar cvar gvar].to_set.freeze
23
+ FLAT_INTERPOLATION = %i[ivar cvar gvar nth_ref].to_set.freeze
24
24
 
25
25
  private_constant(*constants(false))
26
26
 
@@ -42,7 +42,7 @@ module Unparser
42
42
  private
43
43
 
44
44
  def heredoc_header
45
- need_squiggly? ? '<<~HEREDOC' : '<<-HEREDOC'
45
+ '<<-HEREDOC'
46
46
  end
47
47
 
48
48
  def heredoc?
@@ -55,11 +55,7 @@ module Unparser
55
55
 
56
56
  def emit_heredoc_body
57
57
  nl
58
- if need_squiggly?
59
- emit_squiggly_heredoc_body
60
- else
61
- emit_normal_heredoc_body
62
- end
58
+ emit_normal_heredoc_body
63
59
  end
64
60
 
65
61
  def emit_heredoc_footer
@@ -119,10 +115,6 @@ module Unparser
119
115
  n_str?(last) && last.children.first[-1].eql?("\n")
120
116
  end
121
117
 
122
- def need_squiggly?
123
- children.any?(s(:str, ''))
124
- end
125
-
126
118
  def emit_squiggly_heredoc_body
127
119
  buffer.indent
128
120
  children.each do |child|
@@ -20,6 +20,10 @@ module Unparser
20
20
  end
21
21
  end
22
22
 
23
+ def emit_heredoc_reminders
24
+ emitter(body).emit_heredoc_reminders
25
+ end
26
+
23
27
  def emit_postcontrol
24
28
  visit(body)
25
29
  writer_with(Resbody, rescue_body).emit_postcontrol
@@ -45,7 +45,7 @@ module Unparser
45
45
  def effective_writer_class
46
46
  if details.binary_syntax_allowed?
47
47
  Binary
48
- elsif details.selector_unary_operator?
48
+ elsif details.selector_unary_operator? && n_send?(node)
49
49
  Unary
50
50
  elsif write_as_attribute_assignment?
51
51
  AttributeAssignment
@@ -75,20 +75,7 @@ module Unparser
75
75
  end
76
76
 
77
77
  def emit_normal_arguments
78
- parentheses do
79
- arguments.each_with_index do |node, index|
80
- write(', ') unless index.zero?
81
- emit_argument(node, index.succ.equal?(arguments.length))
82
- end
83
- end
84
- end
85
-
86
- def emit_argument(argument, last)
87
- if n_hash?(argument) && last
88
- writer_with(Emitter::Hash, argument).emit_last_argument_hash
89
- else
90
- visit(argument)
91
- end
78
+ parentheses { delimited(arguments) }
92
79
  end
93
80
 
94
81
  def emit_heredoc_reminder(argument)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unparser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Schirp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-09 00:00:00.000000000 Z
11
+ date: 2020-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: abstract_type
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: 2.6.5
117
+ version: 3.0.0
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: 2.6.5
124
+ version: 3.0.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: procto
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -142,28 +142,28 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 0.9.13
145
+ version: 0.10.21
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 0.9.13
152
+ version: 0.10.21
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: mutant-rspec
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: 0.9.13
159
+ version: 0.10.21
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: 0.9.13
166
+ version: 0.10.21
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: rspec
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -198,42 +198,42 @@ dependencies:
198
198
  requirements:
199
199
  - - "~>"
200
200
  - !ruby/object:Gem::Version
201
- version: 1.2.0
201
+ version: 1.3.0
202
202
  type: :development
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
206
  - - "~>"
207
207
  - !ruby/object:Gem::Version
208
- version: 1.2.0
208
+ version: 1.3.0
209
209
  - !ruby/object:Gem::Dependency
210
210
  name: rubocop
211
211
  requirement: !ruby/object:Gem::Requirement
212
212
  requirements:
213
213
  - - "~>"
214
214
  - !ruby/object:Gem::Version
215
- version: 0.92.0
215
+ version: '1.7'
216
216
  type: :development
217
217
  prerelease: false
218
218
  version_requirements: !ruby/object:Gem::Requirement
219
219
  requirements:
220
220
  - - "~>"
221
221
  - !ruby/object:Gem::Version
222
- version: 0.92.0
222
+ version: '1.7'
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: rubocop-packaging
225
225
  requirement: !ruby/object:Gem::Requirement
226
226
  requirements:
227
227
  - - "~>"
228
228
  - !ruby/object:Gem::Version
229
- version: 0.5.0
229
+ version: '0.5'
230
230
  type: :development
231
231
  prerelease: false
232
232
  version_requirements: !ruby/object:Gem::Requirement
233
233
  requirements:
234
234
  - - "~>"
235
235
  - !ruby/object:Gem::Version
236
- version: 0.5.0
236
+ version: '0.5'
237
237
  description: Generate equivalent source for parser gem AST nodes
238
238
  email: mbj@schirp-dso.com
239
239
  executables:
@@ -285,17 +285,20 @@ files:
285
285
  - lib/unparser/emitter/in_match.rb
286
286
  - lib/unparser/emitter/in_pattern.rb
287
287
  - lib/unparser/emitter/index.rb
288
+ - lib/unparser/emitter/kwargs.rb
288
289
  - lib/unparser/emitter/kwbegin.rb
289
290
  - lib/unparser/emitter/lambda.rb
290
291
  - lib/unparser/emitter/masgn.rb
291
292
  - lib/unparser/emitter/match.rb
292
293
  - lib/unparser/emitter/match_alt.rb
293
294
  - lib/unparser/emitter/match_as.rb
295
+ - lib/unparser/emitter/match_pattern.rb
294
296
  - lib/unparser/emitter/match_rest.rb
295
297
  - lib/unparser/emitter/match_var.rb
296
298
  - lib/unparser/emitter/mlhs.rb
297
299
  - lib/unparser/emitter/module.rb
298
300
  - lib/unparser/emitter/op_assign.rb
301
+ - lib/unparser/emitter/pair.rb
299
302
  - lib/unparser/emitter/pin.rb
300
303
  - lib/unparser/emitter/primitive.rb
301
304
  - lib/unparser/emitter/range.rb
@@ -331,7 +334,10 @@ files:
331
334
  homepage: http://github.com/mbj/unparser
332
335
  licenses:
333
336
  - MIT
334
- metadata: {}
337
+ metadata:
338
+ bug_tracker_uri: https://github.com/mbj/unparser/issues
339
+ changelog_uri: https://github.com/mbj/unparser/blob/master/Changelog.md
340
+ funding_uri: https://github.com/sponsors/mbj
335
341
  post_install_message:
336
342
  rdoc_options: []
337
343
  require_paths:
@@ -340,14 +346,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
340
346
  requirements:
341
347
  - - ">="
342
348
  - !ruby/object:Gem::Version
343
- version: '0'
349
+ version: '2.5'
344
350
  required_rubygems_version: !ruby/object:Gem::Requirement
345
351
  requirements:
346
352
  - - ">="
347
353
  - !ruby/object:Gem::Version
348
354
  version: '0'
349
355
  requirements: []
350
- rubygems_version: 3.1.4
356
+ rubygems_version: 3.2.3
351
357
  signing_key:
352
358
  specification_version: 4
353
359
  summary: Generate equivalent source for parser gem AST nodes