unparser 0.5.1 → 0.5.6

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 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