• Stars
    star
    310
  • Rank 134,926 (Top 3 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 11 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Turn Ruby AST into semantically equivalent Ruby source

unparser

CI Gem Version

Generate equivalent source for ASTs from parser.

The following constraints apply:

  • No support for macruby extensions
  • Only support for the modern AST format
  • Only support for Ruby >= 2.7

Notable Users:

(if you want your tool to be mentioned here please PR the addition with a TLDR of your use case).

Public API:

While unparser is in the 0.x versions its public API can change any moment. I recommend to use ~> 0.x.y style version constraints that should give the best mileage.

Usage

require 'parser/current'
require 'unparser'

ast = Unparser.parse('your(ruby(code))')

Unparser.unparse(ast) # => 'your(ruby(code))'

To preserve the comments from the source:

require 'parser/current'
require 'unparser'

ast, comments = Unparser.parse_with_comments('your(ruby(code)) # with comments')

Unparser.unparse(ast, comments) # => 'your(ruby(code)) # with comments'

Passing in manually constructed AST:

require 'parser/current'
require 'unparser'

module YourHelper
  def s(type, *children)
    Parser::AST::Node.new(type, children)
  end
end

include YourHelper

node = s(:def,
  :foo,
  s(:args,
    s(:arg, :x)
  ),
  s(:send,
    s(:lvar, :x),
    :+,
    s(:int, 3)
  )
)

Unparser.unparse(node) # => "def foo(x)\n  x + 3\nend"

Note: DO NOT attempt to pass in nodes generated via AST::Sexp#s, these ones return API incompatible AST::Node instances, unparser needs Parser::AST::Node instances.

Equivalent vs identical:

require 'unparser'

node = Unparser.parse(<<~'RUBY')
  %w[foo bar]
RUBY

generated = Unparser.unparse(node) # ["foo", "bar"], NOT %w[foo bar] !

code == generated                 # false, not identical code
Unparser.parse(generated) == node # true, but identical AST

Summary: unparser does not reproduce your source! It produces equivalent source.

Ruby Versions:

Unparsers primay reason for existance is mutant and its supported Ruby-Versions.

Basically: All non EOL MRI releases.

If you need to generate Ruby Syntax outside of this band feel free to contact me (email in gemspec).

Testing:

Unparser currently successfully round trips almost all ruby code around. Using Ruby >= 2.6. If there is a non round trippable example that is NOT subjected to known Limitations. please report a bug.

On CI unparser is currently tested against rubyspec with minor excludes.

Limitations:

Source parsed with magic encoding headers other than UTF-8 and that have literal strings. where parts can be represented in UTF-8 will fail to get reproduced.

A fix is possible as with latest updates the parser gem carries the information.

Example:

Original-Source:

# -*- encoding: binary -*-

"\x98\x76\xAB\xCD\x45\x32\xEF\x01\x01\x23\x45\x67\x89\xAB\xCD\xEF"

Original-AST:

(str "\x98v\xAB\xCDE2\xEF\x01\x01#Eg\x89\xAB\xCD\xEF")

Generated-Source:

"\x98v\xAB\xCDE2\xEF\x01\x01#Eg\x89\xAB\xCD\xEF"

Generated-AST:

(str "\x98v\xAB\xCDE2\xEF\u0001\u0001#Eg\x89\xAB\xCD\xEF")

Diff:

@@ -1,2 +1,2 @@
-(str "\x98v\xAB\xCDE2\xEF\x01\x01#Eg\x89\xAB\xCD\xEF")
+(str "\x98v\xAB\xCDE2\xEF\u0001\u0001#Eg\x89\xAB\xCD\xEF")

Installation

Install the gem unparser via your prefered method.

People

Various people contributed to this repository. See Contributors.

Included Libraries

For dependency reduction reasons unparser ships vendored (and reduced) versions of:

Contributing

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don't break it in a future version unintentionally.
  • Commit, do not mess with version (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

Known Users

  • RailsRocket - A no-code app builder that creates Rails apps

License

See LICENSE file.

More Repositories

1

mutant

Automated code reviews via mutation testing - semantic code coverage.
Ruby
1,950
star
2

anima

Object initializer from attributes hash
Ruby
173
star
3

stratosphere

Haskell EDSL and type-checker for AWS CloudFormation templates
Haskell
162
star
4

vanguard

External validations for ruby objects
Ruby
120
star
5

concord

Mixin to ease compositions in ruby
Ruby
112
star
6

devtools

The rake ci task!
Ruby
64
star
7

inflecto

Inflector for ruby
46
star
8

auom

Algebra with units of measurement.
Ruby
27
star
9

axiom-mongo-adapter

An MongoDB adapter for Axiom
Ruby
11
star
10

esearch

A ruby driver for elasticsearch that is ONLY A DRIVER.
Ruby
11
star
11

axiom-arango-adapter

An ArangoDB adapter for Axiom
Ruby
8
star
12

mhs

Haskell tooling megarepo
Haskell
8
star
13

axiom-elasticsearch-adapter

An Elasticsearch adapter for Axiom.
Ruby
8
star
14

mprelude-rb

Ruby
7
star
15

to_source

Generator for equivalent source from rubinius AST
Ruby
7
star
16

aql

The ArangoDB AQL AST and to_source implementation
Ruby
7
star
17

ruby-cdb

Ruby cdb reader and writer
C
6
star
18

guard-mutant

Mutant integration for guard
Ruby
6
star
19

mapper

A simple mapper without a latin name. (abandoned)
Ruby
6
star
20

axiom-fuzzer

A fuzzer for axiom relations
Ruby
6
star
21

assets

Playground for a nicer asset system
Ruby
6
star
22

response

Build HTTP responses
Ruby
5
star
23

request

Abstract not only the rack env in something more nice
Ruby
5
star
24

pgt

SQL Golden Testing Tool for postgresql
Haskell
5
star
25

ffprobe

Ruby wrapper around ffprobe
Ruby
4
star
26

eventstorm

unfinished zmq based event aggregation framework
Ruby
4
star
27

tasty-mgolden

A different golden testing provider for tasty.
Haskell
4
star
28

morpher

Transformation of ruby data-structures with optionally traced evaluation
Ruby
4
star
29

rz

Ruby ZeroMQ based jobserver with truly pulling workers
Ruby
3
star
30

openapi

OpenAPI datatypes
Haskell
3
star
31

axiom-sexp

Generate and load veritas relations from / to s-expressions
Ruby
3
star
32

lht

Lambda haskell tool / builds static binaries inside alpine containers
Haskell
3
star
33

db-migrations

Haskell Database Migrations for Postgresql
Haskell
3
star
34

ducktrap

The old soon to be unmaintained ducktrap. Successor is mbj/morpher
Ruby
3
star
35

source-constraints

GHC plugins to constrain the haskell source
Haskell
3
star
36

stack-deploy

Tooling around cloudformation templates
Haskell
3
star
37

variable

Ruby concurrency variables MVar and IVar
Ruby
2
star
38

mutant-rails-example

Mutant with rails example
Ruby
2
star
39

conversions

Haskell type conversions, another one.
Haskell
2
star
40

cbt

Container backend tool
2
star
41

devtools-hs

Haskell development tooling
Haskell
2
star
42

navigation

A web navigation dry up package
Ruby
1
star
43

sitemap_xml

Incomplete sitemap xml generator
Ruby
1
star
44

sunits

Depreciated sunits repo. Only used since some of my older projects will install from here!
Ruby
1
star
45

dump-parser

Simple and dump string 2 value DSL
Ruby
1
star
46

custom-resource

Custom CloudFormation Resources
Haskell
1
star
47

tinymagick

Simple ruby wrapper around imagemagick tools "identify" and "mogrify"
Ruby
1
star
48

html

Because XSS-free HTML generation is not about String#html_safe?
Ruby
1
star
49

mprelude

Very minimal prelude
Haskell
1
star
50

mcake

Ruby
1
star
51

dm-annoing-modificators

Modification methods that raise on failure for datamapper.
Ruby
1
star
52

apk-build

My APK overlay and builder
Shell
1
star