Skip to content

Latest commit

 

History

History
143 lines (101 loc) · 4.93 KB

CONTRIBUTING.md

File metadata and controls

143 lines (101 loc) · 4.93 KB

Contributing

Want to contribute? There's a few moving parts that you'll need to know about:

  • Ripper - The Ruby Parser used by this Project
  • Prettier - Provides building blocks for formatting documents in a stylistic way
  • Testing - Ensuring that there are no formatting or semantic regressions

Your input Ruby code is parsed by Ripper, and pretty printed using the building blocks provided by Prettier. Jest tests are used to protect against regressions and allow for test driving the development.

Ripper

Ripper is the built-in CRuby lexer and parser that understands your Ruby code. It is able to read your source code and provide access to the tokens and the abstract syntax tree associated with your code.

You can explore Ripper within an interactive Ruby terminal. The process of identifying the tokens within your source code is called lexing:

$ irb
> require 'ripper'
 => true
> Ripper.tokenize("puts('hello world')")
 => ["puts", "(", "'", "hello world", "'", ")"]

Once the tokens are understood, Ripper constructs an abstract syntax tree:

$ irb
> require 'ripper'
> pp Ripper.sexp("puts('hello world')")
[:program,
 [[:method_add_arg,
   [:fcall, [:@ident, "puts", [1, 0]]],
   [:arg_paren,
    [:args_add_block,
     [[:string_literal,
       [:string_content, [:@tstring_content, "hello world", [1, 6]]]]],
     false]]]]]

Sometimes it can be useful to view this visually with Ripper Preview.

The JavaScript Prettier process spawns a Ruby process within parse.js, which interacts with a custom wrapper written around Ripper called RipperJS. By default Ripper discards source code comments from the abstract syntax view. RipperJS attempts to bridge this gap by attaching the original comments to the abstract syntax tree generated by Ripper. Full details are within ripper.rb

If you want to check out the enhanced abstract syntax tree generated by RipperJS:

bin/sexp file.rb

Or to view the output on a code snippet:

bin/sexp "# comment example\nputs('hello world')"

It's worth noting that there are multiple Ruby parsers available, but for this project Ripper has been chosen for the following reasons:

  • Ripper is the built in reference implementation for CRuby
  • Ripper is stable and always provides access to the latest syntax that Ruby supports
  • Ripper is written in C, and it's fast

Useful links

Prettier

Prettier provides support for third party plugins by providing access to its document builders. In plugin-ruby the input Ruby file is parsed with Ripper, then printed with Prettier. The printing logic for Ruby can be found within print.js

Useful links

Testing

There are two types of testing performed within this project:

  • Visual formatting regressions
  • Semantic regressions

Formatting regressions are verified by running the Prettier plugin against a series of pre-determined Ruby test cases and saving the the output to a file for later comparison. If in the future Prettier formats this file differently, the tests will no longer match the stored snapshot and fail. The JavaScript testing framework Jest provides this functionality. Rubocop is additionally ran over these files to ensure that they also match the community standards.

Semantic regressions are verified with with Minitest. After formatting the Ruby test cases the file is ran with Minitest to ensure that it behaves exactly the same way before and after formatting has been applied.

Useful commands

After checking out the repo, run yarn and bundle to install dependencies.

Running tests

yarn run test

Updating Jest snapshots

yarn run test -u

Viewing the output of RipperJS on a file

bin/sexp file.rb

Viewing the output of RipperJS on code

bin/sexp 'your_ruby_code(1, 2, 3)'

Viewing the output of Prettier on a file

bin/print file.rb

Viewing the output of Prettier on code

bin/print 'your_ruby_code(1, 2, 3)'