unparser 0.3.0 → 0.4.0

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: 96674256a364b20d34279b13821b1885615189db24c4ec229405b8305936fa4d
4
- data.tar.gz: 1c5484ef44c86310837ad8626635228e56bf3227e11e3d4190f0159cb52dfc58
3
+ metadata.gz: 52e96163f8fc7a9a3da3464e326997c9dc5a094225806e0f2fc72e0474a97026
4
+ data.tar.gz: 719ac295c33e15c44cbe9bff91920536367b37409e71fb407f1fecef2cd69dbf
5
5
  SHA512:
6
- metadata.gz: f5784148f66b8283b4b56a48f7b93c116b069a947ee3196012444bade8f02a67fb080cd52d6011068c8cdcf7ac82efe07bf1b3c2e7aa7215d66313369aa5e469
7
- data.tar.gz: ce7223635f503a065e8d4826d6967817d9165adf76c424105bfc690f9c1b5dfee6c87dbb320c4ccb72af9ebcb78eb4b3fa2319977d89f0eb892e940bfd6b5eb6
6
+ metadata.gz: 661ff992d06f1c3f1ff05e66ecd789c08fc91432af9e082a036309a6d74bec83e99b58026f1e85080c86f2b8ab8d01de08bb8e743225e5204690670c9d0f280e
7
+ data.tar.gz: 338124c08c6e241f70f587db3e149da9562dfd18550bae2e1f4d6afaa76f9e3b9d39dae37ca1d81e7ff97d50e246a2a56faa984edb4988c05e9e69d6880d12ba
@@ -1,17 +1,41 @@
1
1
  defaults: &defaults
2
2
  working_directory: ~/unparser
3
- steps:
4
- - checkout
5
- - run: bundle install
6
- - run: bundle exec rake ci
3
+ docker:
4
+ - image: circleci/ruby:2.5.3
7
5
  version: 2
8
6
  jobs:
9
- ruby_2_5:
7
+ unit_specs:
10
8
  <<: *defaults
11
- docker:
12
- - image: circleci/ruby:2.5.3
9
+ steps:
10
+ - checkout
11
+ - run: bundle install
12
+ - run: bundle exec rspec spec/unit
13
+ integration_specs:
14
+ <<: *defaults
15
+ steps:
16
+ - checkout
17
+ - run: bundle install
18
+ - run: bundle exec rspec spec/integration
19
+ metrics:
20
+ <<: *defaults
21
+ steps:
22
+ - checkout
23
+ - run: bundle install
24
+ - run: bundle exec rake metrics:rubocop
25
+ - run: bundle exec rake metrics:reek
26
+ - run: bundle exec rake metrics:flay
27
+ - run: bundle exec rake metrics:flog
28
+ mutant:
29
+ <<: *defaults
30
+ steps:
31
+ - checkout
32
+ - run: bundle install
33
+ - run: bundle exec rake metrics:mutant
13
34
  workflows:
14
35
  version: 2
15
36
  test:
16
37
  jobs:
17
- - ruby_2_5
38
+ - unit_specs
39
+ - integration_specs
40
+ - metrics
41
+ - mutant
@@ -1,3 +1,8 @@
1
+ # v0.4.0 2018-12-01
2
+
3
+ * Change to modern AST format.
4
+ * Add experimental `Unparser.{parser,parse,parse_with_comments}`
5
+
1
6
  # v0.3.0 2018-11-16
2
7
 
3
8
  * Drop support for Ruby < 2.5
data/Gemfile CHANGED
@@ -3,3 +3,5 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
+
7
+ gem 'mutant', git: 'https://github.com/mbj/mutant', branch: 'change/to-modern-ast'
@@ -1,7 +1,31 @@
1
+ GIT
2
+ remote: https://github.com/mbj/mutant
3
+ revision: 6b36372385ec1bedc0d170470e65d7d33740769e
4
+ branch: change/to-modern-ast
5
+ specs:
6
+ mutant (0.8.20)
7
+ abstract_type (~> 0.0.7)
8
+ adamantium (~> 0.2.0)
9
+ anima (~> 0.3.0)
10
+ ast (~> 2.2)
11
+ concord (~> 0.1.5)
12
+ diff-lcs (~> 1.3)
13
+ equalizer (~> 0.0.9)
14
+ ice_nine (~> 0.11.1)
15
+ memoizable (~> 0.4.2)
16
+ morpher (~> 0.2.6)
17
+ parser (~> 2.5.1)
18
+ procto (~> 0.0.2)
19
+ regexp_parser (~> 1.2)
20
+ unparser (~> 0.3.0)
21
+ mutant-rspec (0.8.20)
22
+ mutant (~> 0.8.20)
23
+ rspec-core (>= 3.4.0, < 4.0.0)
24
+
1
25
  PATH
2
26
  remote: .
3
27
  specs:
4
- unparser (0.2.9)
28
+ unparser (0.4.0)
5
29
  abstract_type (~> 0.0.7)
6
30
  adamantium (~> 0.2.0)
7
31
  concord (~> 0.1.5)
@@ -82,25 +106,6 @@ GEM
82
106
  equalizer (~> 0.0.9)
83
107
  ice_nine (~> 0.11.0)
84
108
  procto (~> 0.0.2)
85
- mutant (0.8.19)
86
- abstract_type (~> 0.0.7)
87
- adamantium (~> 0.2.0)
88
- anima (~> 0.3.0)
89
- ast (~> 2.2)
90
- concord (~> 0.1.5)
91
- diff-lcs (~> 1.3)
92
- equalizer (~> 0.0.9)
93
- ice_nine (~> 0.11.1)
94
- memoizable (~> 0.4.2)
95
- morpher (~> 0.2.6)
96
- parallel (~> 1.3)
97
- parser (~> 2.5.1)
98
- procto (~> 0.0.2)
99
- regexp_parser (~> 1.2)
100
- unparser (~> 0.2.5)
101
- mutant-rspec (0.8.19)
102
- mutant (~> 0.8.19)
103
- rspec-core (>= 3.4.0, < 4.0.0)
104
109
  parallel (1.12.1)
105
110
  parser (2.5.3.0)
106
111
  ast (~> 2.4.0)
@@ -166,6 +171,7 @@ DEPENDENCIES
166
171
  anima (~> 0.3.0)
167
172
  devtools (~> 0.1.21)
168
173
  morpher (~> 0.2.6)
174
+ mutant!
169
175
  unparser!
170
176
 
171
177
  BUNDLED WITH
data/README.md CHANGED
@@ -7,12 +7,12 @@ unparser
7
7
  [![Gem Version](https://img.shields.io/gem/v/unparser.svg)](https://rubygems.org/gems/unparser)
8
8
 
9
9
  Generate equivalent source for ASTs from whitequarks [parser](https://github.com/whitequark/parser).
10
- Excluding the macruby extensions the parser gem implemnents on top of ruby syntax.
11
10
 
12
- Excluding the MacRuby / RubyMotion extensions the parser gem implemenents on top of MRI Ruby
13
- syntax starting with parser release 2.3. If you feel the need to get them supported, contact me.
11
+ The following constraints apply:
14
12
 
15
- This library is able to reproduce 100% of Ruby 2.1 - 2.3 syntax. Including its own source code.
13
+ * No support for macruby extensions
14
+ * Only support for the [modern AST](https://github.com/whitequark/parser/#usage) format
15
+ * Only support for Ruby >= 2.5
16
16
 
17
17
  It serves well for [mutant](https://github.com/mbj/mutant) mutators and the in-memory vendoring for self hosting,
18
18
  and other tooling.
@@ -20,15 +20,19 @@ and other tooling.
20
20
  Public API:
21
21
  -----------
22
22
 
23
- While unparser is in the `0.x` versions its public API can change any moment. I recommend to use `~> 0.x.y` style
24
- version constraints that should give the best mileage.
23
+ While unparser is in the `0.x` versions its public API can change any moment.
24
+ I recommend to use `~> 0.x.y` style version constraints that should give the best mileage.
25
25
 
26
26
  Usage
27
27
  -----
28
28
 
29
29
  ```ruby
30
+ require 'parser/current'
30
31
  require 'unparser'
31
- Unparser.unparse(your_ast) # => "the code"
32
+
33
+ ast = Unpaser.parse('your(ruby(code))')
34
+
35
+ Unparser.unparse(ast) # => 'your(ruby(code))'
32
36
  ```
33
37
 
34
38
  To preserve the comments from the source:
@@ -36,8 +40,10 @@ To preserve the comments from the source:
36
40
  ```ruby
37
41
  require 'parser/current'
38
42
  require 'unparser'
39
- ast, comments = Parser::CurrentRuby.parse_with_comments(your_source)
40
- Unparser.unparse(ast, comments) # => "the code # with comments"
43
+
44
+ ast, comments = Unpaser.parse_with_comments('your(ruby(code)) # with comments')
45
+
46
+ Unparser.unparse(ast, comments) # => 'your(ruby(code)) # with comments'
41
47
  ```
42
48
 
43
49
  Passing in manually constructed AST:
@@ -71,22 +77,19 @@ Unparser.unparse(node) # => "def foo(x)\n x + 3\nend"
71
77
  Note: DO NOT attempt to pass in nodes generated via `AST::Sexp#s`, these ones return
72
78
  API incompatible `AST::Node` instances, unparser needs `Parser::AST::Node` instances.
73
79
 
74
-
75
80
  Equivalent vs identical:
76
81
 
77
82
  ```ruby
78
83
  require 'unparser'
79
84
 
80
- code = <<-RUBY
81
- %w(foo bar)
85
+ node = Unparser.parse(<<~'RUBY')
86
+ %w[foo bar]
82
87
  RUBY
83
88
 
84
- node = Parser::CurrentRuby.parse(code)
85
-
86
- generated = Unparser.unparse(node) # ["foo", "bar"], NOT %w(foo bar) !
89
+ generated = Unparser.unparse(node) # ["foo", "bar"], NOT %w[foo bar] !
87
90
 
88
91
  code == generated # false, not identical code
89
- Parser::CurrentRuby.parse(generated) == node # true, but identical AST
92
+ Unparser.parse(generated) == node # true, but identical AST
90
93
  ```
91
94
 
92
95
  Summary: unparser does not reproduce your source! It produces equivalent source.
@@ -94,7 +97,7 @@ Summary: unparser does not reproduce your source! It produces equivalent source.
94
97
  Testing:
95
98
  --------
96
99
 
97
- Unparser currently successfully round trips almost all ruby code around. Using MRI-2.0.0.
100
+ Unparser currently successfully round trips almost all ruby code around. Using MRI-2.5.x.
98
101
  If there is a non round trippable example that is NOT subjected to known [Limitations](#limitations).
99
102
  please report a bug.
100
103
 
@@ -106,10 +109,7 @@ Limitations:
106
109
  Source parsed with magic encoding headers other than UTF-8 and that have literal strings.
107
110
  where parts can be represented in UTF-8 will fail to get reproduced.
108
111
 
109
- Please note: If you are on 1.9.3 or any 1.9 mode ruby and use UTF-8 encoded source via the magic encoding header:
110
- Unparser does not reproduce these.
111
-
112
- A fix might be possible and requires some guessing or parser metadata the raw AST does not carry.
112
+ A fix is possible as with latest updates the parser gem carries the information.
113
113
 
114
114
  Example:
115
115
 
@@ -1,3 +1,3 @@
1
1
  ---
2
2
  threshold: 13
3
- total_score: 632
3
+ total_score: 640
@@ -11,8 +11,7 @@ detectors:
11
11
  exclude: []
12
12
  ControlParameter:
13
13
  enabled: true
14
- exclude:
15
- - Mutant::Expression#match_length
14
+ exclude: []
16
15
  DataClump:
17
16
  enabled: true
18
17
  exclude: []
@@ -31,9 +30,7 @@ detectors:
31
30
  exclude: []
32
31
  LongParameterList:
33
32
  enabled: true
34
- exclude:
35
- - Mutant::Matcher::Method::Instance#self.build
36
- - Mutant::Meta::Example::DSL # 3 vars
33
+ exclude: []
37
34
  max_params: 2
38
35
  LongYieldList:
39
36
  enabled: true
@@ -41,55 +38,30 @@ detectors:
41
38
  max_params: 2
42
39
  NestedIterators:
43
40
  enabled: true
44
- exclude:
45
- - Mutant#self.singleton_subclass_instance
46
- - Mutant::CLI#parse
47
- - Mutant::Mutator::Node::Arguments#emit_argument_mutations
48
- - Mutant::Mutator::Node::Resbody#mutate_captures
49
- - Mutant::Mutator::Util::Array::Element#dispatch
50
- - Mutant::Parallel::Master#run
51
- - Mutant::RequireHighjack#self.call
52
- - Mutant::Selector::Expression#call
53
- - Parser::Lexer#self.new
41
+ exclude: []
54
42
  max_allowed_nesting: 1
55
43
  ignore_iterators: []
56
44
  NilCheck:
57
45
  enabled: false
58
46
  RepeatedConditional:
59
47
  enabled: true
60
- exclude:
61
- - Mutant::Mutator
62
- - Mutant::Meta::Example::DSL
48
+ exclude: []
63
49
  max_ifs: 1
64
50
  TooManyInstanceVariables:
65
51
  enabled: true
66
- exclude:
67
- - Mutant::Mutator # 4 vars
68
- - Mutant::Parallel::Master # 4 vars
69
- - Mutant::Meta::Example::DSL # 4 vars
52
+ exclude: []
70
53
  max_instance_variables: 3
71
54
  TooManyMethods:
72
55
  enabled: true
73
- exclude:
74
- - Mutant::CLI
75
- - Mutant::Mutator::Node
76
- - Mutant::Parallel::Master
56
+ exclude: []
77
57
  max_methods: 10
78
58
  TooManyStatements:
79
59
  enabled: true
80
- exclude:
81
- - Mutant::CLI#add_debug_options
82
- - Mutant::CLI#add_environment_options
83
- - Mutant::Reporter::CLI::Printer::Config#run
84
- - Mutant::Reporter::CLI::Printer::EnvProgress#run
85
- - Mutant::Runner#run_driver
86
- - Mutant::Zombifier::File#self.find
60
+ exclude: []
87
61
  max_statements: 7
88
62
  UncommunicativeMethodName:
89
63
  enabled: true
90
- exclude:
91
- - Mutant::AST::Sexp#s
92
- - Mutant::Mutation#sha1
64
+ exclude: []
93
65
  reject:
94
66
  - '/^[a-z]$/'
95
67
  - '/[0-9]$/'
@@ -123,15 +95,4 @@ detectors:
123
95
  exclude: []
124
96
  UtilityFunction:
125
97
  enabled: true
126
- exclude:
127
- - Mutant::AST::Sexp#s
128
- - Mutant::Actor::Env#new_mailbox
129
- - Mutant::CLI#reporter
130
- - Mutant::Integration::Null#call
131
- - Mutant::Integration::Rspec#parse_example
132
- - Mutant::Integration::Rspec#parse_expression # intentional, private
133
- - Mutant::Meta::Example::Verification#format_mutations # intentional, private
134
- - Mutant::Reporter::CLI::Format::Progressive#new_buffer
135
- - Mutant::Reporter::CLI::Printer::StatusProgressive#object # False positive calls super
136
- - Mutant::Repository::Diff#tracks? # intentional, private
137
- - Mutant::Repository::Diff#within_working_directory? # intentional, private
98
+ exclude: []
@@ -8,10 +8,15 @@ require 'parser/current'
8
8
 
9
9
  # Library namespace
10
10
  module Unparser
11
+ # Unparser specific AST builder defaulting to modern AST format
12
+ class Builder < Parser::Builders::Default
13
+ modernize
14
+ end
11
15
 
12
16
  EMPTY_STRING = ''.freeze
17
+ EMPTY_ARRAY = [].freeze
13
18
 
14
- EMPTY_ARRAY = [].freeze
19
+ private_constant(*constants(false))
15
20
 
16
21
  # Unparse an AST (and, optionally, comments) into a string
17
22
  #
@@ -31,6 +36,60 @@ module Unparser
31
36
  buffer.content
32
37
  end
33
38
 
39
+ # Parse string into AST
40
+ #
41
+ # @param [String] source
42
+ #
43
+ # @return [Parser::AST::Node]
44
+ def self.parse(source)
45
+ parser.parse(buffer(source))
46
+ end
47
+
48
+ # Parse string into AST, with comments
49
+ #
50
+ # @param [String] source
51
+ #
52
+ # @return [Parser::AST::Node]
53
+ def self.parse_with_comments(source)
54
+ parser.parse_with_comments(buffer(source))
55
+ end
56
+
57
+ # Parser instance that produces AST unparser understands
58
+ #
59
+ # @return [Parser::Base]
60
+ #
61
+ # @api private
62
+ #
63
+ # ignore :reek:NestedIterators
64
+ def self.parser
65
+ Parser::CurrentRuby.new(Builder.new).tap do |parser|
66
+ parser.diagnostics.tap do |diagnostics|
67
+ diagnostics.all_errors_are_fatal = true
68
+ diagnostics.consumer = method(:consume_diagnostic)
69
+ end
70
+ end
71
+ end
72
+
73
+ # Consume diagnostic
74
+ #
75
+ # @param [Parser::Diagnostic] diagnostic
76
+ #
77
+ # @return [undefined]
78
+ def self.consume_diagnostic(diagnostic)
79
+ Kernel.warn(diagnostic.render)
80
+ end
81
+ private_class_method :consume_diagnostic
82
+
83
+ # Construct a parser buffer from string
84
+ #
85
+ # @param [String] source
86
+ #
87
+ # @return [Parser::Source::Buffer]
88
+ def self.buffer(source)
89
+ Parser::Source::Buffer.new('(string)').tap do |buffer|
90
+ buffer.source = source
91
+ end
92
+ end
34
93
  end # Unparser
35
94
 
36
95
  require 'unparser/buffer'
@@ -56,7 +115,6 @@ require 'unparser/emitter/meta'
56
115
  require 'unparser/emitter/send'
57
116
  require 'unparser/emitter/send/unary'
58
117
  require 'unparser/emitter/send/binary'
59
- require 'unparser/emitter/send/index'
60
118
  require 'unparser/emitter/send/regular'
61
119
  require 'unparser/emitter/send/conditional'
62
120
  require 'unparser/emitter/send/arguments'
@@ -93,5 +151,7 @@ require 'unparser/emitter/flipflop'
93
151
  require 'unparser/emitter/rescue'
94
152
  require 'unparser/emitter/resbody'
95
153
  require 'unparser/emitter/ensure'
154
+ require 'unparser/emitter/index'
155
+ require 'unparser/emitter/lambda'
96
156
  # make it easy for zombie
97
157
  require 'unparser/finalize'
@@ -16,7 +16,7 @@ module Unparser
16
16
  #
17
17
  # FIXME: Kwargs are missing.
18
18
  #
19
- ASSIGN_NODES = %i[lvasgn arg optarg restarg].freeze
19
+ ASSIGN_NODES = %i[arg lvasgn optarg procarg0 restarg].freeze
20
20
 
21
21
  # Test for local variable inherited scope reset
22
22
  #