NodeMutation
NodeMutation provides a set of APIs to rewrite node source code.
Installation
Add this line to your application's Gemfile:
gem 'node_mutation'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install node_mutation
Usage
- initialize the NodeMutation instance:
require 'node_mutation'
mutation = NodeMutation.new(source, adapter: :parser)
- call the rewrite apis:
# append the code to the current node.
mutation.append node, 'include FactoryGirl::Syntax::Methods'
# delete source code of the child ast node
mutation.delete node, :dot, :message, and_comma: true
# indent code
mutation.indent node, tab_size: 1
# insert code to the ast node.
mutation.insert node, 'URI.', at: 'beginning'
# prepend code to the ast node.
mutation.prepend node, '{{arguments.first}}.include FactoryGirl::Syntax::Methods'
# remove source code of the ast node
mutation.remove node, and_comma: true
# replace child node of the ast node with new code
mutation.replace node, :message, with: 'test'
# replace the ast node with new code
mutation.replace_with node, 'create {{arguments}}'
# wrap node with prefix and suffix code
mutation.wrap node, prefix: 'module Foo', suffix: 'end', newline: true
# no operation
mutation.noop
# group actions
mutation.group do
mutation.delete node, :message, :dot
mutation.replace node, 'receiver.caller.message', with: 'flat_map'
end
- process actions and write the new source code to file:
result = mutation.process
# if it makes any change to the source
result.affected?
# if any action is conflicted
result.conflicted
# return the new source if it is affected
result.new_source
Evaluated Value
NodeMutation supports to evaluate the value of the node, and use the evaluated value to rewrite the source code.
source = 'after_commit :do_index, on: :create, if: :indexable?'
node = Parser::CurrentRuby.parse(source)
mutation.replace node, '{{arguments.-1.on_value}}', with: ':update'
source # after_commit :do_index, on: :update, if: :indexable?
See more in PrismAdapter and ParserAdapter and SyntaxTreeAdapter
Configuration
adapter
Different parsers, like prism, parse and syntax_tree, will generate different AST nodes, to make NodeMutation work for them all, we define an Adapter interface, if you implement the Adapter interface, you can set it as NodeMutation's adapter.
It provides 3 adapters
PrismAdapter
ParserAdapter
SyntaxTreeAdapter
strategy
It provides 3 strategies to handle conflicts when processing actions:
-
Strategy.KEEP_RUNNING
: keep running and ignore the conflict action. -
Strategy.THROW_ERROR
: throw error when conflict action is found.
NodeMutation.configure(strategy: Strategy.KEEP_RUNNING); // default is Strategy.THROW_ERROR
tab_width
NodeMutation.configure(tab_width: 4); // default is 2
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and the created tag, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/synvert-hq/node_mutation.